該程序寫入SQLite數據庫,消息通過無線模塊接收。但不知何故,每次收到一條消息並將其寫入數據庫時,都會發生內存泄漏,因爲大約10 000次寫入程序使用的是1GB內存。使用sqlite3與C++時的內存泄露
爲SQLite3 with C++的文件說,內存泄漏阻止與sqlite3_finalize()
和sqlite3_close()
其中存在:
#include <iostream>
#include <string>
#include <sstream>
#include "sqlite3.h"
using namespace std;
#define DB "test.db"
sqlite3 *dbfile;
bool connectDB();
void disonnectDB();
int insOrUpdate(string s);
int select(string s);
struct messageStruct_t {
float value;
};
bool isOpenDB = false;
int main() {
int counter = 0;
while (1) {
int header = 1;
int message = rand() % 3;
if (message) {
counter ++;
switch (header) {
case 1: {
messageStruct_t recMessage;
recMessage.value = 55;
int receivedSendersID = 2;
//SQL query to get foreign key
stringstream strm_select;
strm_select << "SELECT id FROM table1 WHERE sendersID="
<< receivedSendersID;
string s_select = strm_select.str();
cout << "SQL query: " << s_select << endl;
int sendersID = select(s_select);
cout << "Sender's ID: " << sendersID << endl;
if (sendersID == 0) {
cout << "Error: Sender doesn't exist\n";
} else {
stringstream strm_insert;
strm_insert << "INSERT into table2(id,value,sender_id) values("
<< counter << ", "
<< recMessage.value << ", " << sendersID << ")";
string s_insert = strm_insert.str();
cout << "SQL query: " << s_insert << endl;
insOrUpdate(s_insert);
cout << "Recorded data: " << recMessage.value << endl;
}
}
default: {
break;
}
}
}
}
}
bool connectDB() {
if (sqlite3_open(DB, &dbfile) == SQLITE_OK) {
isOpenDB = true;
return true;
}
return false;
}
void disonnectDB() {
if (isOpenDB == true) {
sqlite3_close(dbfile);
}
}
int insOrUpdate(string s) {
if (!connectDB()) {
return 0;
}
char *str = &s[0];
sqlite3_stmt *statement;
int result;
const char *query = str;
if (sqlite3_prepare(dbfile, query, -1, &statement, 0) == SQLITE_OK) {
result = sqlite3_step(statement);
//the documentation says that this destroys the statement and prevents memory leaks
sqlite3_finalize(statement);
return result;
}
//and this destroys the db object and prevents memory leaks
disonnectDB();
return 0;
}
int select(string s) {
if (!connectDB()) {
return 0;
}
char *str = &s[0];
sqlite3_stmt *statement;
const char *query = str;
string returned;
if (sqlite3_prepare(dbfile, query, -1, &statement, 0) == SQLITE_OK) {
int ctotal = sqlite3_column_count(statement);
int res = 0;
while (1) {
res = sqlite3_step(statement);
if (res == SQLITE_ROW) {
for (int i = 0; i < ctotal; i++) {
string s = (char*)sqlite3_column_text(statement, i);
cout << s << " ";
returned = s;
}
cout << endl;
}
if (res == SQLITE_DONE || res == SQLITE_ERROR) {
cout << "done " << endl;
break;
}
}
} else {
cout << "Can't prepare" << endl;
return 0;
}
sqlite3_finalize(statement);
disonnectDB();
int result;
stringstream convert(returned);
if (!(convert >> result)) {
result = 0;
}
return result;
}
CREATE TABLE table1 (
id INTEGER NOT NULL,
sendersID INTEGER,
PRIMARY KEY (id)
);
CREATE TABLE table2 (
id INTEGER NOT NULL,
value FLOAT,
sender_id INTEGER,
FOREIGN KEY(sender_id) REFERENCES table1 (id)
);
INSERT INTO table1(sendersID) values(2);
請將樣本減少到可編譯運行的樣本。目前我需要發明'message','headerStruct','header'和'recMessage'甚至編譯它,希望實際的錯誤實際上是在你粘貼的代碼中,而不是在你選擇的某個部分中選擇的粘貼.... – Rumburak
我修改了代碼進行編譯。我非常確定泄漏出現在那裏,因爲應用程序使用的內存在程序沒有收到消息時不會增長。 –
@Rumburak,我添加了一個測試數據庫。內存泄露在這裏,4000次寫入後爲300MB。 –