PDA

View Full Version : memory leak - where?



Tomasz
1st September 2010, 10:08
Hello!

I've got my simple application, but it causes memory leak. I think one of this three functions is a problem:



bool MainWindow::pobierzKomunikaty()
{
bool ok;
QTextStream out(stdout);
QString zapytanie;
QSqlRecord rec;
QSqlQueryModel queryModel;

QFont font;
font.setPointSize(7);

odczytanoOstatnieKomunikaty=0;

ok = bdb.open();

if (ok)
{
out << endl << "Otworzylem baze!" << endl ;
} else {
out << "Nie udalo sie otworzyc bazy!" << endl;
}

queryModel.setQuery("SELECT * FROM server_notifications WHERE complete='0'", bdb); //LIMIT 1

liczbaWiadomosci = queryModel.rowCount();

bdb.close();

out << "Mamy: " << liczbaWiadomosci << " wiadomosci!" << endl;


for(int i=0 ; i<liczbaWiadomosci; i++)
{
rec = queryModel.record(i);


out << rec.value(1).toString() << ": ";
out << rec.value(2).toString() << endl;

QMessageBox *msgBox=new QMessageBox;

if(rec.value(1).toString()=="warning") msgBox->setIcon(QMessageBox::Warning);
else if (rec.value(1).toString()=="info") msgBox->setIcon(QMessageBox::Information);
else if (rec.value(1).toString()=="error") msgBox->setIcon(QMessageBox::Critical);

msgBox->setFont(font);

msgBox->setWindowTitle(rec.value(1).toString());
msgBox->setText(rec.value(2).toString());

QSpacerItem* horizontalSpacer = new QSpacerItem(240, 290, QSizePolicy::Minimum, QSizePolicy::Minimum);
QGridLayout* layout = (QGridLayout*)msgBox->layout();
layout->addItem(horizontalSpacer, layout->rowCount(), 0, 1, layout->columnCount());

msgBox->move(0,0);
msgBox->exec();

delete msgBox;

ok = bdb.open();

zapytanie.clear();
zapytanie="update server_notifications set complete='1'";
zapytanie.append(" where id='");
zapytanie.append(QString::number(rec.value(0).toIn t()));
zapytanie.append("'");

QSqlQuery *query=new QSqlQuery;

query->clear();
query->prepare(zapytanie);
ok = query->exec();

bdb.close();

delete query;
}

odczytanoOstatnieKomunikaty=1;

return ok;
}

bool MainWindow::wyswietlKomunikaty()
{
if(odczytanoOstatnieKomunikaty==0)
{

} else
{
pobierzKomunikaty();
odczytajNotificationInterval();
timer->start(notificationInterval);
}

return 1;
}

bool MainWindow::odczytajNotificationInterval()
{
bool ok;
QTextStream out(stdout);
QSqlRecord rec;
QSqlQueryModel queryModel;

ok = bdb.open();

if (ok)
{
out << endl << "Otworzylem baze!" << endl ;
} else {
out << "Nie udalo sie otworzyc bazy!" << endl;
}

queryModel.setQuery("SELECT * FROM config WHERE name='qt-notification-interval'", bdb);

rec = queryModel.record(0);
notificationInterval = (rec.value(1).toInt())*1000;

out << "Notification interval: " << notificationInterval << " ms" << endl;

bdb.close();

return ok;
}


Maybe someone can tell me where?

thanks in advance
best regards
Tomasz

wysota
1st September 2010, 10:21
There is no memory leak here. But you are needlessly creating objects on heap and not on the stack (like the QSqlQuery object).

Tomasz
1st September 2010, 10:34
So I should create all the objects one time in my *.h file as a private objects?
One question to my code - after exiting each function all the objects are being deleted from memory?

And one more piece of code from beginning:



MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
setWindowFlags(Qt::CustomizeWindowHint|Qt::Framele ssWindowHint);

databaseName="/mybase";
bdb = QSqlDatabase::addDatabase("QSQLITE");
bdb.setDatabaseName(databaseName);

connect(ui->pomiaryButton, SIGNAL(clicked()), this, SLOT(uruchomPomiary()));
connect(ui->sterowanieButton, SIGNAL(clicked()), this, SLOT(uruchomSterowanie()));
connect(ui->klimaButton, SIGNAL(clicked()), this, SLOT(uruchomKlima()));
connect(ui->konfiguracjaButton, SIGNAL(clicked()), this, SLOT(uruchomKonfiguracja()));

odczytanoOstatnieKomunikaty=0;

odczytajNotificationInterval();

timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(wyswietlKomunikaty()));
timer->start(notificationInterval);

this->show();

pobierzKomunikaty();
}


Now it's the whole code. Maybe somewhere here is memory leak? I'm thinking about memory leak because each time I check how many resources programs needs (by 'ps' in linux console) my application take more resources.

thanks in advance
best regards
Tomasz

wysota
1st September 2010, 10:46
So I should create all the objects one time in my *.h file as a private objects?
No. If you have an "int" variable somewhere in your code do you create it as:
int x; or
int *x = new int;?

Are any of those "private obejcts"?


One question to my code - after exiting each function all the objects are being deleted from memory?
The ones that are created on the stack are deleted automatically as the stack unwinds, the ones created in dynamic memory (heap) have to be released manually (unless they are parented QObjects, I'm sure you know the drill...).


Maybe somewhere here is memory leak?
If you don't have a corresponding "removeDatabase" to each "addDatabase" I suspect there could be a memory leak. I'm not sure if Qt releases the old connection when it detects a new one with the same name (but you surely get warning messages to the console if you are trying to reuse name of an active db connection).

Tomasz
1st September 2010, 10:54
I create my "private" variables as:



int x;


But what about this objects in functions - all of them are created on heap or stack? I need to remove them?

thanks in advance
best regards
Tomasz

wysota
1st September 2010, 11:19
I create my "private" variables as:



int x;

What about others? Have you ever (anywhere) created an int using the "new" operator?

Tomasz
1st September 2010, 11:32
The only thing created with "new" is timer:



private:
Ui::MainWindow *ui;
QString databaseName;
int liczbaWiadomosci;
QTimer *timer;
int odczytanoOstatnieKomunikaty;
int notificationInterval;
QSqlDatabase bdb;


So I don't need to remove variables that I have in my function manually? Because I never did that in "pure" C/C++. As I remember I only need to remove things created with "new" operator.

thanks in advance
best regards
Tomasz

wysota
1st September 2010, 11:50
The only thing created with "new" is timer:
Look at the first snippet you provided and examine that. Especially the QSqlQuery instance.

Tomasz
1st September 2010, 11:55
Yes, You're right, but after using it I'm deleting it, right?

thanks in advance
best regards
Tomasz

wysota
1st September 2010, 12:34
Yes, You're right, but after using it I'm deleting it, right?
Yes, but there is no point in creating it on the heap (using the "new" operator) and having to worry about deleting it afterwards. Simply create the query and the message box on the stack and the compiler will take care of deleting them for you.

Tomasz
1st September 2010, 12:42
So, reassuming. Now If I don't change anything (later I will take care about what You said) there is no reason to worry about memory leak in this code above?

thanks in advance
best regards
Tomasz

wysota
1st September 2010, 12:54
Except the database issue, yes. But in general it's best to run your code through memory leak detection tool such as valgrind and see what it has to say.

Tomasz
1st September 2010, 13:17
I'll check it with valgrind. Is it necessary to use removeDatabase if I'm adding it only once at the beginning and then only using open/close on that database? Should I remove it and add it again after every open/close cycle?

thanks in advance
best regards
Tomasz

wysota
1st September 2010, 14:04
If you add it once then you remove it once. You said your application was increasing its memory usage and you gave the code snippet where you suspected the leak to be so I assumed it was being ran multiple times. We don't consider a leak something that lives throughout the whole life of the application and is not deleted anywhere (although it's still considered "improper"). A leak is when you repeat this process thoughout the life of the application, like so:

for(int i=0;i<10;i++){
QString *var = new QString("xxx"); // memory is allocated 10 times and never released although the variable is not reachable anymore
}

Tomasz
1st September 2010, 19:10
I've used valgrind, and it says:



LEAK SUMMARY:
definitely lost: 768 bytes in 4 blocks
indirectly lost: 2,840 bytes in 141 blocks
possibly lost: 1,119,616 bytes in 4,885 blocks
still reachable: 585,094 bytes in 5,456 blocks
suppressed: 0 bytes in 0 blocks


Maybe I can post full code of my app (it's not long) and someone could tell me what I'm doing wrong?

thanks in advance
best regards
Tomasz

P.S. Even if I run the simplest application valgrind says that some memory is lost, but not as much as above.

wysota
1st September 2010, 19:17
Rerun valgrind with --leak-check=full --show-reachable=yes

Tomasz
1st September 2010, 19:28
I've ran it with that options for a while and it says:



LEAK SUMMARY:
definitely lost: 1,792 bytes in 8 blocks
indirectly lost: 8,400 bytes in 418 blocks
possibly lost: 5,756,014 bytes in 7,557 blocks
still reachable: 1,967,661 bytes in 8,582 blocks
suppressed: 0 bytes in 0 blocks

SixDegrees
1st September 2010, 19:35
I've ran it with that options for a while and it says:



LEAK SUMMARY:
definitely lost: 1,792 bytes in 8 blocks
indirectly lost: 8,400 bytes in 418 blocks
possibly lost: 5,756,014 bytes in 7,557 blocks
still reachable: 1,967,661 bytes in 8,582 blocks
suppressed: 0 bytes in 0 blocks


Well, it says a good deal more than that. Valgrind gives you a detailed report not only on the total amount of memory leaked, but where it was leaked, right down to the line number. You'll want to compile in debug mode to get the best report, but even without debugging information it's usually possible to track down the portion of code responsible for a leak.

Read through the valgrind documentation so you know what you're looking at.

Tomasz
1st September 2010, 19:51
Well, it says a good deal more than that.

Yes, It says really a lot of things. Sometimes it says about errors even in 'clean' application (window only) just created in Qt Creator. I don't have a lot of experience with valgrind, I'm reading documentation but still have no idea how to track that leaks. Code looks fine for me.

thaks in advance
best regards
Tomasz

wysota
1st September 2010, 19:58
Sometimes you can get false positives so it's important to understand why certain things are reported. But you should get a very detailed output with a place in code and reason for every leak.

Tomasz
1st September 2010, 21:04
Report like this?



==29102== 3,392 bytes in 143 blocks are possibly lost in loss record 371 of 380
==29102== at 0x4023C4C: malloc (vg_replace_malloc.c:195)
==29102== by 0x50146F3: ??? (in /usr/lib/libfontconfig.so.1.4.4)
==29102== by 0x5019579: ??? (in /usr/lib/libfontconfig.so.1.4.4)
==29102== by 0x501A982: ??? (in /usr/lib/libfontconfig.so.1.4.4)
==29102== by 0x5368A54: ??? (in /usr/lib/libexpat.so.1.5.2)
==29102== by 0x53698A0: ??? (in /usr/lib/libexpat.so.1.5.2)
==29102== by 0x536ADB0: ??? (in /usr/lib/libexpat.so.1.5.2)
==29102== by 0x536B969: ??? (in /usr/lib/libexpat.so.1.5.2)
==29102== by 0x536264B: XML_ParseBuffer (in /usr/lib/libexpat.so.1.5.2)
==29102== by 0x50187FA: FcConfigParseAndLoad (in /usr/lib/libfontconfig.so.1.4.4)
==29102== by 0x5018B43: FcConfigParseAndLoad (in /usr/lib/libfontconfig.so.1.4.4)
==29102== by 0x501A038: ??? (in /usr/lib/libfontconfig.so.1.4.4)


It's from application where nothing happens - there's only window.

Sorry I'm very stubborn about this memory leak but I've wrote some applications and all of them works fine on PC but on ARM after some time applications starting to work very slow and it looks like everything freezes (especially applications which uses SQLite databases). I suppose It's memory leak (applications are not complicated). Maybe I should look for cause somewhere else?

thanks in advance
best regards
Tomasz

SixDegrees
1st September 2010, 23:27
Wait - you suppose it's a memory leak? You're not sure? Why do you think it's a memory leak?

You aren't going to find solutions to your problems unless you describe them correctly. Use a tool like 'top' to monitor your application's memory usage over time, and see if it increases indefinitely. Or if there's some runaway CPU process bogging down the system. Or try netstat if you're connecting to a remote server, to see if there's some aberrant network activity that might be causing the slowdown.

Or, if you're really fixated on believing it's a memory issue, why not simply try destroying the connection you started off suspecting, and see if that makes the problem go away?

Or you can continue to pore over the valgrind output, looking for bytes marked as definitely lost; as you can see, it provides references back to the line in your source code where the problem originated.

Tomasz
2nd September 2010, 11:22
Use a tool like 'top' to monitor your application's memory usage over time, and see if it increases indefinitely.

I've used 'top' and memory increases all the time the program works. Maybe someone could check my project (it's really short) because I have no idea what I'm doing wrong. I will be really grateful I can only guess it can by connected with databases...

thanks in advance
best regards
Tomasz

wysota
2nd September 2010, 12:36
Does valgrind report leaks in your code?

Tomasz
2nd September 2010, 13:00
Yes It reports memory leaks as I said earlier. He reports it's connected with database functions (I'm still learning to use valgrind so I can't say nothing more now) but I know it happens mostly when I'm using functions that are doing something with database... so it would be nice if someone check my whole code because I think I'm doing the same mistake in every app...

thanks in advance
best regards
Tomasz

wysota
2nd September 2010, 13:30
Yes It reports memory leaks as I said earlier. He reports it's connected with database functions (I'm still learning to use valgrind so I can't say nothing more now) but I know it happens mostly when I'm using functions that are doing something with database... so it would be nice if someone check my whole code because I think I'm doing the same mistake in every app...
Please show us the relevant sections of the report and corresponding lines of your source code.

Tomasz
2nd September 2010, 22:24
Using valgrind for QT is very difficult. It report about 84000 errors (like "Conditional jump or move depends on uninitialised value(s)"). I really don't know what is important here. I was observing my program and I've noticed that memory is growing while I'm using function in code below.



bool MainWindow::pobierzKomunikaty()
{
bool ok;
QTextStream out(stdout);
QString zapytanie;
QSqlRecord rec;
QSqlQueryModel queryModel;
QSqlQuery query;
QFont font;

font.setPointSize(7);

odczytanoOstatnieKomunikaty=0;

ok = bdb.open();

if (ok)
{
out << endl << "Otworzylem baze!" << endl ;
} else {
out << "Nie udalo sie otworzyc bazy!" << endl;
}

queryModel.clear();

queryModel.setQuery("SELECT * FROM server_notifications WHERE complete='0'", bdb);

liczbaWiadomosci = queryModel.rowCount();

bdb.close();

#ifdef DEBUG
out << "Mamy: " << liczbaWiadomosci << " wiadomosci!" << endl;
#endif


for(int i=0 ; i<liczbaWiadomosci; i++)
{
rec = queryModel.record(i);


#ifdef DEBUG
out << rec.value(1).toString() << ": ";
out << rec.value(2).toString() << endl;
#endif

QMessageBox *msgBox=new QMessageBox;

if(rec.value(1).toString()=="warning") msgBox->setIcon(QMessageBox::Warning);
else if (rec.value(1).toString()=="info") msgBox->setIcon(QMessageBox::Information);
else if (rec.value(1).toString()=="error") msgBox->setIcon(QMessageBox::Critical);

if(rec.value(1).toString()!="confirmation")
{
msgBox->setFont(font);
msgBox->setWindowTitle(rec.value(1).toString());
msgBox->setText(rec.value(2).toString());

QSpacerItem* horizontalSpacer = new QSpacerItem(240, 290, QSizePolicy::Minimum, QSizePolicy::Minimum);
QGridLayout* layout = (QGridLayout*)msgBox->layout();
layout->addItem(horizontalSpacer, layout->rowCount(), 0, 1, layout->columnCount());

msgBox->move(0,0);
msgBox->exec();

delete msgBox;

ok = bdb.open();

zapytanie.clear();
zapytanie="update server_notifications set complete='1'";
zapytanie.append(" where id='");
zapytanie.append(QString::number(rec.value(0).toIn t()));
zapytanie.append("'");

query.clear();
query.prepare(zapytanie);
ok = query.exec();
query.clear();

bdb.close();
} else if (rec.value(1).toString()=="confirmation") {
msgBox->setIcon(QMessageBox::Question);
msgBox->setFont(font);
msgBox->setWindowTitle(rec.value(1).toString());
msgBox->setText(rec.value(2).toString());
msgBox->setStandardButtons(QMessageBox::Yes | QMessageBox::No);

QSpacerItem* horizontalSpacer = new QSpacerItem(240, 290, QSizePolicy::Minimum, QSizePolicy::Minimum);
QGridLayout* layout = (QGridLayout*)msgBox->layout();
layout->addItem(horizontalSpacer, layout->rowCount(), 0, 1, layout->columnCount());

msgBox->move(0,0);
int result = msgBox->exec();

delete msgBox;

ok = bdb.open();

zapytanie.clear();
if (result == QMessageBox::Yes) zapytanie="update server_notifications set complete='2'";
else if (result == QMessageBox::No) zapytanie="update server_notifications set complete='3'";
zapytanie.append(" where id='");
zapytanie.append(QString::number(rec.value(0).toIn t()));
zapytanie.append("'");

query.clear();
query.prepare(zapytanie);
ok = query.exec();
query.clear();

bdb.close();
}
}

zapytanie.clear();
rec.clear();
queryModel.clear();
odczytanoOstatnieKomunikaty=1;

return ok;
}

bool MainWindow::wyswietlKomunikaty()
{
if(odczytanoOstatnieKomunikaty==0)
{

} else
{
pobierzKomunikaty();
odczytajNotificationInterval();
timer.start(notificationInterval);
}

return 1;
}

bool MainWindow::odczytajNotificationInterval()
{
bool ok;
QTextStream out(stdout);
QSqlRecord rec;
QSqlQueryModel queryModel;

ok = bdb.open();


if (ok)
{
out << endl << "Otworzylem baze!" << endl ;
} else {
out << "Nie udalo sie otworzyc bazy!" << endl;
}

queryModel.clear();

queryModel.setQuery("SELECT * FROM config WHERE name='qt-notification-interval'", bdb);

rec = queryModel.record(0);
notificationInterval = (rec.value(1).toInt())*1000;

#ifdef DEBUG
out << "Notification interval: " << notificationInterval << " ms" << endl;
#endif

rec.clear();
queryModel.clear();
bdb.close();

return ok;
}


And really I can't say nothing more. Like I said valgrind generates thousands of messages for QT applications. Problem is important because when program runs on ARM it takes minute after minute more memory resources.

thanks in advance
best regards
Tomasz

wysota
3rd September 2010, 07:34
Here is an example app:

#include <QtGui>


int main(int argc, char **argv){
QApplication app(argc, argv);
QLineEdit *le = new QLineEdit;
QString *str = new QString("xxx");
le->setText(*str);
le->show();
return app.exec();
}

And valgrind report for it (the parts that are relevant):

==12196== HEAP SUMMARY:
==12196== in use at exit: 195,287 bytes in 2,848 blocks
==12196== total heap usage: 72,096 allocs, 69,248 frees, 10,244,645 bytes allocated
==12196==
==12196== 4 bytes in 1 blocks are definitely lost in loss record 27 of 566
==12196== at 0x40244F0: operator new(unsigned int) (vg_replace_malloc.c:214)
==12196== by 0x8048811: main (main.cpp:7)
==12196==
==12196== 16,548 (20 direct, 16,528 indirect) bytes in 1 blocks are definitely lost in loss record 566 of 566
==12196== at 0x40244F0: operator new(unsigned int) (vg_replace_malloc.c:214)
==12196== by 0x80487ED: main (main.cpp:6)
==12196==
==12196== LEAK SUMMARY:
==12196== definitely lost: 1,401 bytes in 19 blocks
==12196== indirectly lost: 16,548 bytes in 113 blocks
==12196== possibly lost: 60,653 bytes in 611 blocks
==12196== still reachable: 116,685 bytes in 2,105 blocks
==12196== suppressed: 0 bytes in 0 blocks
==12196== Reachable blocks (those to which a pointer was found) are not shown.
==12196== To see them, rerun with: --leak-check=full --show-reachable=yes
==12196==
==12196== For counts of detected and suppressed errors, rerun with: -v
==12196== ERROR SUMMARY: 135 errors from 135 contexts (suppressed: 123 from 9)
You can see it immediately says where to look for problems. The rest of the reports in my case are either false positives or caused by Qt's dependencies (like KDE or fontconfig).

Tomasz
4th September 2010, 20:38
I've checked program with valgrind. It produced hundreds of messages.

It' starts with:


==27551== HEAP SUMMARY:
==27551== in use at exit: 6,339,826 bytes in 16,037 blocks
==27551== total heap usage: 239,607 allocs, 223,570 frees, 63,095,584 bytes allocated
==27551==
==27551== 2 bytes in 1 blocks are possibly lost in loss record 5 of 3,561
==27551== at 0x4023C4C: malloc (vg_replace_malloc.c:195)
==27551== by 0x50F2ED3: g_malloc (in /lib/libglib-2.0.so.0.2400.1)
==27551== by 0x510B768: g_strdup (in /lib/libglib-2.0.so.0.2400.1)
==27551== by 0x5121060: g_get_language_names (in /lib/libglib-2.0.so.0.2400.1)
==27551== by 0x51153F9: g_thread_init_glib (in /lib/libglib-2.0.so.0.2400.1)
==27551== by 0x50A360D: g_thread_init (in /usr/lib/libgthread-2.0.so.0.2400.1)
==27551== by 0x4CFEAF0: QEventDispatcherGlibPrivate::QEventDispatcherGlibP rivate(_GMainContext*) (qeventdispatcher_glib.cpp:297)
==27551== by 0x427F4CF: QGuiEventDispatcherGlibPrivate::QGuiEventDispatche rGlibPrivate() (qguieventdispatcher_glib.cpp:171)
==27551== by 0x427F5C2: QGuiEventDispatcherGlib::QGuiEventDispatcherGlib(Q Object*) (qguieventdispatcher_glib.cpp:186)
==27551== by 0x4246454: QApplicationPrivate::createEventDispatcher() (qapplication_x11.cpp:606)
==27551== by 0x4CD54B8: QCoreApplication::init() (qcoreapplication.cpp:555)
==27551== by 0x4CD5726: QCoreApplication::QCoreApplication(QCoreApplicatio nPrivate&) (qcoreapplication.cpp:476)


There are a lot of messages like that above not connected directly with my code. Bu I've found a lot of like this:



[...]

==27551== 24 bytes in 1 blocks are possibly lost in loss record 1,088 of 3,561
==27551== at 0x4023C4C: malloc (vg_replace_malloc.c:195)
==27551== by 0x7EFE9CA: sqlite3MemMalloc (sqlite3.c:12607)
==27551== by 0x7EC92CF: mallocWithAlarm (sqlite3.c:15910)
==27551== by 0x7EC93C7: sqlite3Malloc (sqlite3.c:15938)
==27551== by 0x7F1DF40: unixOpen (sqlite3.c:25494)
==27551== by 0x7EC8CF8: sqlite3OsOpen (sqlite3.c:12229)
==27551== by 0x7EEB2F3: sqlite3BtreeFactory (sqlite3.c:34537)
==27551== by 0x7EF4839: openDatabase (sqlite3.c:96157)
==27551== by 0x7EC6774: QSQLiteDriver::open(QString const&, QString const&, QString const&, QString const&, int, QString const&) (qsql_sqlite.cpp:533)
==27551== by 0x4039760: QSqlDatabase::open() (qsqldatabase.cpp:842)
==27551== by 0x804C91F: MainWindow::pobierzKomunikaty() (in /home/tomek/projekt/start-build-desktop/start) //important???
==27551== by 0x804E224: MainWindow::MainWindow(QWidget*) (in /home/tomek/projekt/start-build-desktop/start)

[...]

==27551== 32 bytes in 1 blocks are possibly lost in loss record 1,480 of 3,561
==27551== at 0x4023C4C: malloc (vg_replace_malloc.c:195)
==27551== by 0x7EFE9CA: sqlite3MemMalloc (sqlite3.c:12607)
==27551== by 0x7EC92CF: mallocWithAlarm (sqlite3.c:15910)
==27551== by 0x7EC93C7: sqlite3Malloc (sqlite3.c:15938)
==27551== by 0x7ED6F4B: sqlite3HashInsert (sqlite3.c:19830)
==27551== by 0x7ED8CCC: sqlite3FindCollSeq (sqlite3.c:69693)
==27551== by 0x7EF35DC: createCollation (sqlite3.c:95936)
==27551== by 0x7EF4676: openDatabase (sqlite3.c:96137)
==27551== by 0x7EC6774: QSQLiteDriver::open(QString const&, QString const&, QString const&, QString const&, int, QString const&) (qsql_sqlite.cpp:533)
==27551== by 0x4039760: QSqlDatabase::open() (qsqldatabase.cpp:842)
==27551== by 0x804C91F: MainWindow::pobierzKomunikaty() (in /home/tomek/projekt/start-build-desktop/start)
==27551== by 0x804E224: MainWindow::MainWindow(QWidget*) (in /home/tomek/projekt/start-build-desktop/start)
==27551==
==27551== 32 bytes in 1 blocks are possibly lost in loss record 1,481 of 3,561
==27551== at 0x4023C4C: malloc (vg_replace_malloc.c:195)
==27551== by 0x7EFE9CA: sqlite3MemMalloc (sqlite3.c:12607)
==27551== by 0x7EC92CF: mallocWithAlarm (sqlite3.c:15910)
==27551== by 0x7EC93C7: sqlite3Malloc (sqlite3.c:15938)
==27551== by 0x7ED6F4B: sqlite3HashInsert (sqlite3.c:19830)
==27551== by 0x7ED8CCC: sqlite3FindCollSeq (sqlite3.c:69693)
==27551== by 0x7EF35DC: createCollation (sqlite3.c:95936)
==27551== by 0x7EF46FD: openDatabase (sqlite3.c:96143)
==27551== by 0x7EC6774: QSQLiteDriver::open(QString const&, QString const&, QString const&, QString const&, int, QString const&) (qsql_sqlite.cpp:533)
==27551== by 0x4039760: QSqlDatabase::open() (qsqldatabase.cpp:842)
==27551== by 0x804C91F: MainWindow::pobierzKomunikaty() (in /home/tomek/projekt/start-build-desktop/start)
==27551== by 0x804E224: MainWindow::MainWindow(QWidget*) (in /home/tomek/projekt/start-build-desktop/start)

[...]


And some like this:



==27551== 2,436 (256 direct, 2,180 indirect) bytes in 1 blocks are definitely lost in loss record 3,433 of 3,561
==27551== at 0x4023D47: realloc (vg_replace_malloc.c:476)
==27551== by 0x5270F56: ??? (in /usr/lib/libfontconfig.so.1.4.4)
==27551== by 0x52719AC: ??? (in /usr/lib/libfontconfig.so.1.4.4)
==27551== by 0x52720FB: ??? (in /usr/lib/libfontconfig.so.1.4.4)
==27551== by 0x527231F: ??? (in /usr/lib/libfontconfig.so.1.4.4)
==27551== by 0x5264A27: FcDefaultSubstitute (in /usr/lib/libfontconfig.so.1.4.4)
==27551== by 0x444849A: loadFc(QFontPrivate const*, int, QFontDef const&) (qfontdatabase_x11.cpp:1545)
==27551== by 0x444B8E5: QFontDatabase::load(QFontPrivate const*, int) (qfontdatabase_x11.cpp:1939)
==27551== by 0x4423C29: QFontPrivate::engineForScript(int) const (qfont.cpp:270)
==27551== by 0x443BD26: QFontMetricsF::leading() const (qfontmetrics.cpp:1190)
==27551== by 0x4359653: qt_format_text(QFont const&, QRectF const&, int, QTextOption const*, QString const&, QRectF*, int, int*, int, QPainter*) (qpainter.cpp:7738)
==27551== by 0x435A695: QPainter::drawText(QRect const&, int, QString const&, QRect*) (qpainter.cpp:5807)

[...]

==27551== 4,872 (512 direct, 4,360 indirect) bytes in 2 blocks are definitely lost in loss record 3,483 of 3,561
==27551== at 0x4023D47: realloc (vg_replace_malloc.c:476)
==27551== by 0x5270F56: ??? (in /usr/lib/libfontconfig.so.1.4.4)
==27551== by 0x52719AC: ??? (in /usr/lib/libfontconfig.so.1.4.4)
==27551== by 0x52720FB: ??? (in /usr/lib/libfontconfig.so.1.4.4)
==27551== by 0x527231F: ??? (in /usr/lib/libfontconfig.so.1.4.4)
==27551== by 0x5264A27: FcDefaultSubstitute (in /usr/lib/libfontconfig.so.1.4.4)
==27551== by 0x444849A: loadFc(QFontPrivate const*, int, QFontDef const&) (qfontdatabase_x11.cpp:1545)
==27551== by 0x444B8E5: QFontDatabase::load(QFontPrivate const*, int) (qfontdatabase_x11.cpp:1939)
==27551== by 0x4423C29: QFontPrivate::engineForScript(int) const (qfont.cpp:270)
==27551== by 0x445FC39: QScriptLine::setDefaultHeight(QTextEngine*) (qtextengine.cpp:2009)
==27551== by 0x446F072: QTextLine::layout_helper(int) (qtextlayout.cpp:1756)
==27551== by 0x4470F82: QTextLine::setLineWidth(double) (qtextlayout.cpp:1601)

[...]


And the final summary looks like this:



==27551== LEAK SUMMARY:
==27551== definitely lost: 2,344 bytes in 11 blocks
==27551== indirectly lost: 11,360 bytes in 568 blocks
==27551== possibly lost: 4,787,191 bytes in 8,606 blocks
==27551== still reachable: 1,538,931 bytes in 6,852 blocks
==27551== suppressed: 0 bytes in 0 blocks


I haven't found any message connected directly with code. Functions mentioned in messages I've posted earlier.
Any idea?

thanks in advance
best regards
Tomasz

wysota
5th September 2010, 08:10
These are most likely false positives as you probably don't close the database connection gracefully when you exit your application, but that's ok. It could also be that the application crashes and that's why QCoreApplication's destructor doesn't have a chance to run. The rest of the leaks are unrelated to Qt and you can't do anything about them (apart from not using the offending libraries, such as fontconfig).

Tomasz
5th September 2010, 14:08
These are most likely false positives as you probably don't close the database connection gracefully when you exit your application, but that's ok. It could also be that the application crashes and that's why QCoreApplication's destructor doesn't have a chance to run. The rest of the leaks are unrelated to Qt and you can't do anything about them (apart from not using the offending libraries, such as fontconfig).

My application should work for a long time without problems, but more it's works valgrind shows more memory leaks. I'm always closing database after using it with MyDatabse.close(); Is there anything more I can do to make my application more reliable?

thanks in advance
best regards
Tomasz

wysota
5th September 2010, 14:18
My application should work for a long time without problems, but more it's works valgrind shows more memory leaks.
I don't think Valgrind will show you memory leaks while the program is running. A leak can only be detected with probability close to 100% when the application exits.


I'm always closing database after using it with MyDatabse.close();
There is also QSqlDatabase::removeDatabase() that frees all the resources.


Is there anything more I can do to make my application more reliable?
You need to interpret the memory leak report yourself and review your code to see if you are not leaking memory. Qt itself doesn't leak memory so if you really do have leaks (not that you think you do but that you are certain you do) then it's either in your code or in support libraries (such as db engines, font engines, etc.).

Tomasz
5th September 2010, 14:44
I don't think Valgrind will show you memory leaks while the program is running. A leak can only be detected with probability close to 100% when the application exits.

You're right. I meant that it shows leaks after closing application.
I'll try QSqlDatabase::removeDatabase() and let know how it works.

thanks
best regards
Tomasz

wysota
5th September 2010, 15:19
I'll try QSqlDatabase::removeDatabase() and let know how it works.
Don't expect miracles, it won't make your problems go away and from practical point of view the use of this method is meaningless as in your case you'd only use it when exiting the application anyway so it won't prevent the application from leaking memory.

Tomasz
5th September 2010, 21:20
I think I've found problem. Here we've got code:



ok = bdb.open();

if (ok)
{
queryModel.clear();
queryModel.setQuery("SELECT * FROM notifi WHERE complete='0'", bdb);
queryModel.clear(); // <----- with this everything is OK
bdb.close();
}


And now my question - why if I close my database without clearing QSqlQueryModel strange things happens (data is still there but memory usage is still growing up each time function is executed)? I need to close database for other programs but i need to use data that I've just read from database to QSqlQueryModel.

thanks in advance
best regards
Tomasz

wysota
5th September 2010, 21:41
Destructor of the model will call clear() for you so this is not a memory leak situation. Of course you shouldn't be closing a connection with an active query and you will get a warning on the console when doing so. You should clear all the queries and only then close the database connection.

Tomasz
5th September 2010, 23:47
Of course you shouldn't be closing a connection with an active query and you will get a warning on the console when doing so. You should clear all the queries and only then close the database connection.

In this case I don't get any warning in my console. I'm only observing growing memory usage ('top' command), which disappears when I clean before closing. I'll think I need to learn more about using database in QT. I've got some questions about that problem but I'll search for answers in thread more connected with databases. Thanks!

best regards
Tomasz