Do I have to delete pointers to widgets in FLTK? - c++
So I have the following code:
int main(int, char **) {
auto wptr = new Fl_Double_Window{640,480};
wptr->show();
Fl::run();
return 0;
}
> valgrind --leak-check=full -s ./run
==13685== Memcheck, a memory error detector
==13685== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==13685== Using Valgrind-3.17.0 and LibVEX; rerun with -h for copyright info
==13685== Command: ./run
==13685==
==13685==
==13685== HEAP SUMMARY:
==13685== in use at exit: 741,252 bytes in 1,107 blocks
==13685== total heap usage: 14,853 allocs, 13,746 frees, 2,829,612 bytes allocated
==13685==
==13685== LEAK SUMMARY:
==13685== definitely lost: 0 bytes in 0 blocks
==13685== indirectly lost: 0 bytes in 0 blocks
==13685== possibly lost: 0 bytes in 0 blocks
==13685== still reachable: 741,252 bytes in 1,107 blocks
==13685== suppressed: 0 bytes in 0 blocks
==13685== Reachable blocks (those to which a pointer was found) are not shown.
==13685== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==13685==
==13685== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 1 from 1)
--13685--
--13685-- used_suppression: 1 X on SUSE11 writev uninit padding /usr/lib/valgrind/default.supp:377
==13685==
==13685== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 1 from 1)
Notice I did NOT delete the pointer to the window and valgrind has not detected any leaks.
I have searched the docs (https://www.fltk.org/doc-1.3/basics.html), as well as the FAQ pages (https://www.fltk.org/doc-1.3/FAQ.html, https://www.fltk.org/articles.php), and I've found that the most recent grouping widget automatically attaches newly created widgets, but I've found nothing about how memory is managed by fltk, as in, whether there is some "garbage collector", or if I have to delete the pointer manually.Normally this output would imply that there is some hidden mechanism that is responsible for freeing memory as I have not manually freed the memory allocated for the window and there seems to be no leak, but take a look at the following modification to the previous code:
int main(int, char **) {
auto wptr = new Fl_Double_Window{640,480};
auto box = new Fl_Box{0,0,100,100,"Hello!"}; // Adding widget
wptr->show();
Fl::run();
return 0;
}
valgrind --leak-check=full -s ./run
==14005== Memcheck, a memory error detector
==14005== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==14005== Using Valgrind-3.17.0 and LibVEX; rerun with -h for copyright info
==14005== Command: ./run
==14005==
==14005==
==14005== HEAP SUMMARY:
==14005== in use at exit: 1,101,954 bytes in 11,185 blocks
==14005== total heap usage: 31,631 allocs, 20,446 frees, 7,013,742 bytes allocated
==14005==
==14005== 384 (256 direct, 128 indirect) bytes in 1 blocks are definitely lost in loss record 368 of 540
==14005== at 0x483E7C5: malloc (vg_replace_malloc.c:380)
==14005== by 0x4EC8255: ??? (in /usr/lib/libfontconfig.so.1.12.0)
==14005== by 0x4ECC200: ??? (in /usr/lib/libfontconfig.so.1.12.0)
==14005== by 0x4D433BF: ??? (in /usr/lib/libXft.so.2.3.4)
==14005== by 0x4D438F5: ??? (in /usr/lib/libXft.so.2.3.4)
==14005== by 0x4D43C96: ??? (in /usr/lib/libXft.so.2.3.4)
==14005== by 0x4D44080: XftDefaultHasRender (in /usr/lib/libXft.so.2.3.4)
==14005== by 0x4D44558: XftDefaultSubstitute (in /usr/lib/libXft.so.2.3.4)
==14005== by 0x4D46FD3: XftFontMatch (in /usr/lib/libXft.so.2.3.4)
==14005== by 0x4B30739: Fl_Font_Descriptor::Fl_Font_Descriptor(char const*, int, int) (in /usr/lib/libfltk.so.1.3.7)
==14005== by 0x4B309F2: ??? (in /usr/lib/libfltk.so.1.3.7)
==14005== by 0x4B337BB: fl_normal_label(Fl_Label const*, int, int, int, int, unsigned int) (in /usr/lib/libfltk.so.1.3.7)
==14005==
==14005== 2,565 (768 direct, 1,797 indirect) bytes in 1 blocks are definitely lost in loss record 482 of 540
==14005== at 0x484383F: realloc (vg_replace_malloc.c:1192)
==14005== by 0x4EC830E: ??? (in /usr/lib/libfontconfig.so.1.12.0)
==14005== by 0x4ED94DA: ??? (in /usr/lib/libfontconfig.so.1.12.0)
==14005== by 0x4ED156C: FcFontRenderPrepare (in /usr/lib/libfontconfig.so.1.12.0)
==14005== by 0x4ED1B9D: FcFontMatch (in /usr/lib/libfontconfig.so.1.12.0)
==14005== by 0x4D46FEF: XftFontMatch (in /usr/lib/libXft.so.2.3.4)
==14005== by 0x4B30739: Fl_Font_Descriptor::Fl_Font_Descriptor(char const*, int, int) (in /usr/lib/libfltk.so.1.3.7)
==14005== by 0x4B309F2: ??? (in /usr/lib/libfltk.so.1.3.7)
==14005== by 0x4B337BB: fl_normal_label(Fl_Label const*, int, int, int, int, unsigned int) (in /usr/lib/libfltk.so.1.3.7)
==14005== by 0x4B3390A: Fl_Widget::draw_label(int, int, int, int, unsigned int) const (in /usr/lib/libfltk.so.1.3.7)
==14005== by 0x4AD8D70: Fl_Group::draw_child(Fl_Widget&) const (in /usr/lib/libfltk.so.1.3.7)
==14005== by 0x4AD8F92: Fl_Group::draw_children() (in /usr/lib/libfltk.so.1.3.7)
==14005==
==14005== LEAK SUMMARY:
==14005== definitely lost: 1,024 bytes in 2 blocks
==14005== indirectly lost: 1,925 bytes in 69 blocks
==14005== possibly lost: 0 bytes in 0 blocks
==14005== still reachable: 1,099,005 bytes in 11,114 blocks
==14005== suppressed: 0 bytes in 0 blocks
==14005== Reachable blocks (those to which a pointer was found) are not shown.
==14005== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==14005==
==14005== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 1 from 1)
--14005--
--14005-- used_suppression: 1 X on SUSE11 writev uninit padding /usr/lib/valgrind/default.supp:377
==14005==
==14005== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 1 from 1)
Now it seems that there is a memory leak. It appears that the font library is causing this.I will again modify the code to delete the pointers to the widgets:
int main(int, char **) {
auto wptr = new Fl_Double_Window{640,480};
auto box = new Fl_Box{0,0,100,100,"Hello!"};
wptr->show();
Fl::run();
delete wptr;
delete box;
return 0;
}
> valgrind --leak-check=full ./run
==14238== Memcheck, a memory error detector
==14238== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==14238== Using Valgrind-3.17.0 and LibVEX; rerun with -h for copyright info
==14238== Command: ./run
==14238==
==14238== Invalid read of size 8
==14238== at 0x1091CA: main (main.cpp:64)
==14238== Address 0x58a8730 is 0 bytes inside a block of size 120 free'd
==14238== at 0x48419AB: operator delete(void*, unsigned long) (vg_replace_malloc.c:814)
==14238== by 0x4AD862D: Fl_Group::clear() (in /usr/lib/libfltk.so.1.3.7)
==14238== by 0x4AD86E7: Fl_Group::~Fl_Group() (in /usr/lib/libfltk.so.1.3.7)
==14238== by 0x4AD1889: Fl_Double_Window::~Fl_Double_Window() (in /usr/lib/libfltk.so.1.3.7)
==14238== by 0x1091C0: main (main.cpp:63)
==14238== Block was alloc'd at
==14238== at 0x483EF3F: operator new(unsigned long) (vg_replace_malloc.c:417)
==14238== by 0x10915F: main (main.cpp:60)
==14238==
==14238== Jump to the invalid address stated on the next line
==14238== at 0x0: ???
==14238== by 0x51D4B24: (below main) (in /usr/lib/libc-2.33.so)
==14238== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==14238==
==14238==
==14238== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==14238== Bad permissions for mapped region at address 0x0
==14238== at 0x0: ???
==14238== by 0x51D4B24: (below main) (in /usr/lib/libc-2.33.so)
==14238==
==14238== HEAP SUMMARY:
==14238== in use at exit: 1,156,045 bytes in 11,490 blocks
==14238== total heap usage: 31,586 allocs, 20,096 frees, 7,058,062 bytes allocated
==14238==
==14238== 80 bytes in 1 blocks are possibly lost in loss record 277 of 558
==14238== at 0x483E7C5: malloc (vg_replace_malloc.c:380)
==14238== by 0x53E6D37: ??? (in /usr/lib/libGLdispatch.so.0.0.0)
==14238== by 0x53E73EE: __glDispatchInit (in /usr/lib/libGLdispatch.so.0.0.0)
==14238== by 0x54600AA: ??? (in /usr/lib/libGLX.so.0.0.0)
==14238== by 0x400FE2D: call_init (in /usr/lib/ld-2.33.so)
==14238== by 0x400FF1B: _dl_init (in /usr/lib/ld-2.33.so)
==14238== by 0x40010C9: ??? (in /usr/lib/ld-2.33.so)
==14238==
==14238== 80 bytes in 1 blocks are possibly lost in loss record 278 of 558
==14238== at 0x483E7C5: malloc (vg_replace_malloc.c:380)
==14238== by 0x53E6D37: ??? (in /usr/lib/libGLdispatch.so.0.0.0)
==14238== by 0x53E75D3: __glDispatchRegisterStubCallbacks (in /usr/lib/libGLdispatch.so.0.0.0)
==14238== by 0x538E076: ??? (in /usr/lib/libOpenGL.so.0.0.0)
==14238== by 0x400FE2D: call_init (in /usr/lib/ld-2.33.so)
==14238== by 0x400FF1B: _dl_init (in /usr/lib/ld-2.33.so)
==14238== by 0x40010C9: ??? (in /usr/lib/ld-2.33.so)
==14238==
==14238== 80 bytes in 1 blocks are possibly lost in loss record 279 of 558
==14238== at 0x483E7C5: malloc (vg_replace_malloc.c:380)
==14238== by 0x53E6D37: ??? (in /usr/lib/libGLdispatch.so.0.0.0)
==14238== by 0x53E75D3: __glDispatchRegisterStubCallbacks (in /usr/lib/libGLdispatch.so.0.0.0)
==14238== by 0x4A22076: ??? (in /usr/lib/libGL.so.1.7.0)
==14238== by 0x400FE2D: call_init (in /usr/lib/ld-2.33.so)
==14238== by 0x400FF1B: _dl_init (in /usr/lib/ld-2.33.so)
==14238== by 0x40010C9: ??? (in /usr/lib/ld-2.33.so)
==14238==
==14238== 384 (256 direct, 128 indirect) bytes in 1 blocks are definitely lost in loss record 380 of 558
==14238== at 0x483E7C5: malloc (vg_replace_malloc.c:380)
==14238== by 0x4EC8255: ??? (in /usr/lib/libfontconfig.so.1.12.0)
==14238== by 0x4ECC200: ??? (in /usr/lib/libfontconfig.so.1.12.0)
==14238== by 0x4D433BF: ??? (in /usr/lib/libXft.so.2.3.4)
==14238== by 0x4D438F5: ??? (in /usr/lib/libXft.so.2.3.4)
==14238== by 0x4D43C96: ??? (in /usr/lib/libXft.so.2.3.4)
==14238== by 0x4D44080: XftDefaultHasRender (in /usr/lib/libXft.so.2.3.4)
==14238== by 0x4D44558: XftDefaultSubstitute (in /usr/lib/libXft.so.2.3.4)
==14238== by 0x4D46FD3: XftFontMatch (in /usr/lib/libXft.so.2.3.4)
==14238== by 0x4B30739: Fl_Font_Descriptor::Fl_Font_Descriptor(char const*, int, int) (in /usr/lib/libfltk.so.1.3.7)
==14238== by 0x4B309F2: ??? (in /usr/lib/libfltk.so.1.3.7)
==14238== by 0x4B337BB: fl_normal_label(Fl_Label const*, int, int, int, int, unsigned int) (in /usr/lib/libfltk.so.1.3.7)
==14238==
==14238== 2,565 (768 direct, 1,797 indirect) bytes in 1 blocks are definitely lost in loss record 498 of 558
==14238== at 0x484383F: realloc (vg_replace_malloc.c:1192)
==14238== by 0x4EC830E: ??? (in /usr/lib/libfontconfig.so.1.12.0)
==14238== by 0x4ED94DA: ??? (in /usr/lib/libfontconfig.so.1.12.0)
==14238== by 0x4ED156C: FcFontRenderPrepare (in /usr/lib/libfontconfig.so.1.12.0)
==14238== by 0x4ED1B9D: FcFontMatch (in /usr/lib/libfontconfig.so.1.12.0)
==14238== by 0x4D46FEF: XftFontMatch (in /usr/lib/libXft.so.2.3.4)
==14238== by 0x4B30739: Fl_Font_Descriptor::Fl_Font_Descriptor(char const*, int, int) (in /usr/lib/libfltk.so.1.3.7)
==14238== by 0x4B309F2: ??? (in /usr/lib/libfltk.so.1.3.7)
==14238== by 0x4B337BB: fl_normal_label(Fl_Label const*, int, int, int, int, unsigned int) (in /usr/lib/libfltk.so.1.3.7)
==14238== by 0x4B3390A: Fl_Widget::draw_label(int, int, int, int, unsigned int) const (in /usr/lib/libfltk.so.1.3.7)
==14238== by 0x4AD8D70: Fl_Group::draw_child(Fl_Widget&) const (in /usr/lib/libfltk.so.1.3.7)
==14238== by 0x4AD8F92: Fl_Group::draw_children() (in /usr/lib/libfltk.so.1.3.7)
==14238==
==14238== LEAK SUMMARY:
==14238== definitely lost: 1,024 bytes in 2 blocks
==14238== indirectly lost: 1,925 bytes in 69 blocks
==14238== possibly lost: 240 bytes in 3 blocks
==14238== still reachable: 1,152,856 bytes in 11,416 blocks
==14238== suppressed: 0 bytes in 0 blocks
==14238== Reachable blocks (those to which a pointer was found) are not shown.
==14238== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==14238==
==14238== For lists of detected and suppressed errors, rerun with: -s
==14238== ERROR SUMMARY: 7 errors from 7 contexts (suppressed: 1 from 1)
Segmentation fault (core dumped)
To say the least this modification only worsened the condition XD.In fact, (If I'm not mistaken) the "bad permissions for mapped region..." hints that an attempt has been made to free memory twice, which would suggest that there is indeed some memory management mechanism in fltk.
But then I found this:
How to fix memory leaks in simplest FLTK programm?
Which implies that I should delete the pointers so right now I feel somewhat confused :)
My best guess is that:
(1) the font library is malfunctioning and
(2) FLTK has some internal garbage collector (so I shouldn't delete widget pointers manually so as not to cause any errors), can anyone confirm?
This is 2/3 of the answer. I'll have to try out FLTK on a Linux environment to work out the other 1/3.
FLTK will delete the child widgets when a window is deleted. If you look in the destructor of FL_DoubleWindow, it reads
/**
The destructor <I>also deletes all the children</I>. This allows a
whole tree to be deleted at once, without having to keep a pointer to
all the children in the user code.
*/
Fl_Double_Window::~Fl_Double_Window() {
hide();
}
I can't explain the second case but in the third case, the box is a child of the window and gets deleted when the window gets deleted. So when the code deletes box, it is deleting a deleted item, hence the error.
Valgrind logs clearly show that pointers allocated by Fl_Double_Window and new Fl_Box are not leaked, so it would not be reasonable to try and delete them manually.
The font library has a "leak"; is designed to work this way. Whether it is a good design or not is debatable, but this is the design. When it loads a font, it leaves it there until the application finishes. The application can use any font at any moment. There is no good place to free fonts, other than at application exit, and application exit clears everything up anyway. An application is unlikely to use a billion different fonts (more likely 3 to 10) so there is no risk of filling the memory with unused fonts. If your application does use a billion different fonts, you better find a way to cache them reasonably according to your application needs; a simple font library is unlikely to do a good job of it.
Exhibit A.
I just tried recompiling all three situations (with the -O0 -g ops) and running valgrind: creating an Fl_Double_Window on the stack (leak free), creating an Fl_Double_Window on the heap and not deleting it (leak free), and finally, creating an Fl_Double_Window on the heap and deleting it (leak free).
As someone else noted valgrind shows you the status right before the program exits. valgrind says among others "still reachable: 741,252 bytes in 1,107 blocks" in the OP's message and "Reachable blocks (those to which a pointer was found) are not shown" which means that in case 2 (on the heap) valgrind doesn't report a "leak" because there's still a pointer that points at the window.
Deleting the window (case 3) doesn't change much because it is done right before the program ends and it would release allocated memory anyway. The difference is only that using delete runs the destructors which means that other resources can be freed (buffered data can be written, files can be closed or deleted, etc.).
Whether something should be considered a leak depends on the behavior during runtime. If your program often allocates windows and widgets on the heap and doesn't delete them, then this constitutes a memory leak (but that's not FLTK's fault then). FLTK guarantees that all child widgets of e.g. a window are deleted when the parent window is deleted. That's all. There is no garbage collector running in the background.
But have you managed to find out where the outermost widgets get deleted? In this case the Fl_Double_Window.
FLTK does not delete such outermost widgets - usually windows - by itself. Such widgets are deleted when they go out of scope (if allocated on the stack) or by using operator delete (which is the programmer's responsibility).
Related
Valgrind detects unfreed heap memory usage for a trivial code
My valgrind is telling me that it found non-freed heap memory for the most trivial C++ code. My code is shown as follows: #include <iostream> #include <string> int main() { std::cout << "Hello!!!!" << std::endl; return 0; } And the result of valgrind is here: ==12455== HEAP SUMMARY: ==12455== in use at exit: 72,704 bytes in 1 blocks ==12455== total heap usage: 2 allocs, 1 frees, 73,728 bytes allocated ==12455== ==12455== 72,704 bytes in 1 blocks are still reachable in loss record 1 of 1 ==12455== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==12455== by 0x4EC3EFF: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21) ==12455== by 0x40106C9: call_init.part.0 (dl-init.c:72) ==12455== by 0x40107DA: call_init (dl-init.c:30) ==12455== by 0x40107DA: _dl_init (dl-init.c:120) ==12455== by 0x4000C69: ??? (in /lib/x86_64-linux-gnu/ld-2.23.so) ==12455== ==12455== LEAK SUMMARY: ==12455== definitely lost: 0 bytes in 0 blocks ==12455== indirectly lost: 0 bytes in 0 blocks ==12455== possibly lost: 0 bytes in 0 blocks ==12455== still reachable: 72,704 bytes in 1 blocks ==12455== suppressed: 0 bytes in 0 blocks ==12455== ==12455== For counts of detected and suppressed errors, rerun with: -v ==12455== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) Is this a bug of valgrind?
This is due to the way the C++ standard library works. The containers allocate chunks of memory (called pools) and manage them internally. They use basically a memory manager of their own, rather than relying on system's memory manager. Therefore, when an object is destroyed, it's memory is freed by the internal allocator for reuse, but not given back to the operating system. This is also described in valgrind's FAQ here. To generalize a bit more, valgrind is a very useful tool, but you should not aim for 0 leaks, but rather to understand its reports and find leaks that indicate a problem in the code.
I use valgrind 3.14.0 under Ubuntu 19.04 and i dont get any detections. I ran with --leak-check=fulland without. Maybe its just some versions of valgrind.
valgrind output in C++ of "still reachable" and "possibly lost" blocks do not reference my sources
I am having a hard time pinpointing where do I get memory leaks in my code. The valgrind command I run: valgrind --leak-check=full --log-file=vg1.log --show-leak-kinds=all --leak-resolution=low --track-origins=yes --leak-check-heuristics=all ./enalu_dbg and the output ==22866== Memcheck, a memory error detector ==22866== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. ==22866== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info ==22866== Command: ./enalu_dbg ==22866== Parent PID: 21933 ==22866== ==22866== ==22866== HEAP SUMMARY: ==22866== in use at exit: 47,252 bytes in 240 blocks ==22866== total heap usage: 288 allocs, 48 frees, 55,138 bytes allocated ==22866== ==22866== 4 bytes in 1 blocks are still reachable in loss record 1 of 23 ==22866== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==22866== by 0x77018CD: ??? (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4002.0) ==22866== by 0x7701D28: g_private_get (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4002.0) ==22866== by 0x76DB20C: g_slice_alloc (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4002.0) ==22866== by 0x76AF17D: g_hash_table_new_full (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4002.0) ==22866== by 0x76CF494: g_quark_from_static_string (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4002.0) ==22866== by 0x74314AB: ??? (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4002.0) ==22866== by 0x4010139: call_init.part.0 (dl-init.c:78) ==22866== by 0x4010222: call_init (dl-init.c:36) ==22866== by 0x4010222: _dl_init (dl-init.c:126) ==22866== by 0x4001309: ??? (in /lib/x86_64-linux-gnu/ld-2.19.so) ... ==22866== 184 bytes in 1 blocks are possibly lost in loss record 13 of 23 ==22866== at 0x4C2CE8E: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==22866== by 0x76C56AE: g_realloc (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4002.0) ==22866== by 0x7451618: ??? (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4002.0) ==22866== by 0x74560D4: g_type_register_static (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4002.0) ==22866== by 0x7442DE6: g_param_type_register_static (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4002.0) ==22866== by 0x74449AB: ??? (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4002.0) ==22866== by 0x74315E9: ??? (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4002.0) ==22866== by 0x4010139: call_init.part.0 (dl-init.c:78) ==22866== by 0x4010222: call_init (dl-init.c:36) ==22866== by 0x4010222: _dl_init (dl-init.c:126) ==22866== by 0x4001309: ??? (in /lib/x86_64-linux-gnu/ld-2.19.so) ==22866== ... ==22866== 6,028 bytes in 60 blocks are still reachable in loss record 21 of 23 ==22866== at 0x4C2CC70: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==22866== by 0x76C5668: g_malloc0 (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4002.0) ==22866== by 0x74514D9: ??? (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4002.0) ==22866== by 0x74560D4: g_type_register_static (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4002.0) ==22866== by 0x7442DE6: g_param_type_register_static (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4002.0) ==22866== by 0x744423A: ??? (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4002.0) ==22866== by 0x74315E9: ??? (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4002.0) ==22866== by 0x4010139: call_init.part.0 (dl-init.c:78) ==22866== by 0x4010222: call_init (dl-init.c:36) ==22866== by 0x4010222: _dl_init (dl-init.c:126) ==22866== by 0x4001309: ??? (in /lib/x86_64-linux-gnu/ld-2.19.so) ==22866== ==22866== 10,360 bytes in 5 blocks are still reachable in loss record 22 of 23 ==22866== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==22866== by 0x8B16E9A: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) ==22866== by 0x8B15ACE: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) ==22866== by 0x8B17585: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) ==22866== by 0x8AC9508: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) ==22866== by 0x4010139: call_init.part.0 (dl-init.c:78) ==22866== by 0x4010222: call_init (dl-init.c:36) ==22866== by 0x4010222: _dl_init (dl-init.c:126) ==22866== by 0x4001309: ??? (in /lib/x86_64-linux-gnu/ld-2.19.so) ==22866== ==22866== 16,600 bytes in 4 blocks are still reachable in loss record 23 of 23 ==22866== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==22866== by 0x76C5610: g_malloc (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4002.0) ==22866== by 0x76CF445: g_quark_from_static_string (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4002.0) ==22866== by 0x74314AB: ??? (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4002.0) ==22866== by 0x4010139: call_init.part.0 (dl-init.c:78) ==22866== by 0x4010222: call_init (dl-init.c:36) ==22866== by 0x4010222: _dl_init (dl-init.c:126) ==22866== by 0x4001309: ??? (in /lib/x86_64-linux-gnu/ld-2.19.so) ==22866== ==22866== LEAK SUMMARY: ==22866== definitely lost: 0 bytes in 0 blocks ==22866== indirectly lost: 0 bytes in 0 blocks ==22866== possibly lost: 1,352 bytes in 18 blocks ==22866== still reachable: 45,900 bytes in 222 blocks ==22866== of which reachable via heuristic: ==22866== newarray : 1,536 bytes in 16 blocks ==22866== suppressed: 0 bytes in 0 blocks ==22866== ==22866== For counts of detected and suppressed errors, rerun with: -v ==22866== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0) Most of the records shown (but 1) are "still reachable blocks". I have read that these may be due to delayed pool deallocation. ie deallocations of containers (such as vectors , of which I use alot) after the termination of my main(argc,argv){} function. However, there is surely something wrong because after about 8-9 hours of execution, I clearly see that the executable is using more memory than it started of with (in my pc it started with 0.6% memory usage and after 8h it used about 6%). The problem is that these are cryptic messages - and absolutely none originates from my source files. AS I read here "_dl*" calls are related to linux loader. So how can I pinpoint where the problem originates? I should add that this code uses 1+3 threads(for all blocking operations, ie. to read from stdin and serial port and write data to a file), the boost library (especially circular buffers), and the gsl library. I have however built the code from small proof of concept parts, which do not show any errors/warnings in valgrind. Additionally, I have only a limited number of pointers to class objects in my code, which I verified I delete in the respective destructors.
The original allocation calls are from the shared library initialization code, that gets executed when the shared library your application links with is loaded at runtime, typically before any of your application code actually runs. This is why you don't see your code in the backtrace. It didn't even run yet. The key symbol to look for is _dl_init, the entry point for the shared library initialization. Looking upstream of that tells you which library is being initialized. In your case, it's a bunch of Gnome libraries, and a library called "libpixman". Shared libraries also have a cleanup function that gets invoked when the shared library gets unloaded. A well-organized shared library will use the shared library cleanup function to orderly deallocate all memory that it allocated at startup. Unfortunately, this kind of inattentiveness to detail is sadly common: shared libraries allocating a bunch of memory from the heap, for the shared library's internal static tables, without bothering to deallocate that memory when the shared library gets unloaded. It's unlikely that this is responsible for the memory leaks you're observing while your application is running, except in one case which I'll mention in a moment. It's been my experience that this sloppy allocation practice is only used for static tables that shared libraries allocate once, when they get loaded. The thinking that goes here is that it's not necessary to explicitly clean up after oneself, because the library will only get unloaded once, when the process exits. Sadly, the developers that cut these kind of corners have never heard of dlopen() and dlclose(). This makes it impossible for large applications to load the shared library on demand only when it's needed and unload it afterwards, until it's needed again. So, unless your application code is repeatedly dlopen()ing and dlclose()ing all these Gnome libraries, and libpixman, you'll have to continue looking for your leaks somewhere else. You should read up on, and employ valgrind's suppression files, to suppress this annoying noise from its output.
Interpreting valgrind output for a C++/SDL2 program
Hi can somebody please explain what this valgrind output means and how I should go about fixing this ?? The output I am posting currently is a part of the actual terminal output. The rest is also similar and mostly the same errors are listed. This is for a C++ program using SDL2. The relevant code is really long so I will add whatever is asked in comments. Is this happening due to some SDL_Surface* s? But I made sure to free all of those before returning from main(). Also, my SDL_Window* is global. Can that cause a problem. This output leads to a segfault that arises only in Ubuntu and not in Mac OSX!! I know that Xcode on MAC initializes uninitialized variables and proceeds but the same doesnt happen in Ubuntu. But the valgrind output doesn't show any uninit variables even with trace-origins = yes in memcheck tool. Also, I don't have any functions named call_init or_dl_init or dl_open_worker!! ==17744== 402 bytes in 7 blocks are possibly lost in loss record 506 of 630 ==17744== at 0x4C2CC90: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==17744== by 0xD3A56A1: ??? (in /usr/lib/x86_64-linux-gnu/dri/i965_dri.so) ==17744== by 0xD3A5944: ??? (in /usr/lib/x86_64-linux-gnu/dri/i965_dri.so) ==17744== by 0xD3965C5: ??? (in /usr/lib/x86_64-linux-gnu/dri/i965_dri.so) ==17744== by 0xD152EAF: ??? (in /usr/lib/x86_64-linux-gnu/dri/i965_dri.so) ==17744== by 0x4010139: call_init.part.0 (dl-init.c:78) ==17744== by 0x4010222: call_init (dl-init.c:36) ==17744== by 0x4010222: _dl_init (dl-init.c:126) ==17744== by 0x4014C6D: dl_open_worker (dl-open.c:577) ==17744== by 0x400FFF3: _dl_catch_error (dl-error.c:187) ==17744== by 0x40143AA: _dl_open (dl-open.c:661) ==17744== by 0x601E02A: dlopen_doit (dlopen.c:66) ==17744== by 0x400FFF3: _dl_catch_error (dl-error.c:187) ==17744== 512 bytes in 1 blocks are possibly lost in loss record 519 of 630 ==17744== at 0x4C2CC90: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==17744== by 0xD3D3689: ??? (in /usr/lib/x86_64-linux-gnu/dri/i965_dri.so) ==17744== by 0xD412E86: ??? (in /usr/lib/x86_64-linux-gnu/dri/i965_dri.so) ==17744== by 0xD3D1288: ??? (in /usr/lib/x86_64-linux-gnu/dri/i965_dri.so) ==17744== by 0xB198E60: ??? (in /usr/lib/x86_64-linux-gnu/mesa/libGL.so.1.2.0) ==17744== by 0xB16D9D3: ??? (in /usr/lib/x86_64-linux-gnu/mesa/libGL.so.1.2.0) ==17744== by 0xB16A0BA: ??? (in /usr/lib/x86_64-linux-gnu/mesa/libGL.so.1.2.0) ==17744== by 0xB16A932: glXChooseVisual (in /usr/lib/x86_64-linux-gnu/mesa/libGL.so.1.2.0) ==17744== by 0x4EEDD9E: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.2.0) ==17744== by 0x4EEDFD0: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.2.0) ==17744== by 0x4EE2BE5: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.2.0) ==17744== by 0x4EE477B: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.2.0) ==17744== ==17744== ==17744== LEAK SUMMARY: ==17744== definitely lost: 73,806 bytes in 8 blocks ==17744== indirectly lost: 0 bytes in 0 blocks ==17744== possibly lost: 1,962,378 bytes in 4,720 blocks ==17744== still reachable: 2,908,902 bytes in 5,710 blocks ==17744== suppressed: 0 bytes in 0 blocks ==17744== Reachable blocks (those to which a pointer was found) are not shown. ==17744== To see them, rerun with: --leak-check=full --show-leak-kinds=all ==17744== ==17744== For counts of detected and suppressed errors, rerun with: -v ==17744== ERROR SUMMARY: 194 errors from 186 contexts (suppressed: 5 from 1)
Without knowing the program, the Valgrind output is completely meaningless. For example, you can choose to allocate something globally and never delete it, not even on shutdown. It doesn't hurt in any way, but Valgrind will warn you about a leak, because that's what it is formally. None of this should cause any segfaults though and your interpretation that the output causes it is very questionable. Now, concerning the dl_* functions, those are from the dynamic loader on Linux, so chances are that you didn't cause them. Probably they are something to ignore, which you could try to reproduce by stripping your program down to the point where you are sure that your code doesn't cause any issues. Concerning the global, it doesn't matter either, because a raw pointer doesn't have any destructor. However, if you don't release the resource it represents, Valgrind will report that as error.
Should I Suppress? If so How To Suppress from Makefile
I have several tests that run and in the end I run Valgrind to verify my libraries memory usage. Valgrind consistently complains about: ==27022== HEAP SUMMARY: ==27022== in use at exit: 6,139 bytes in 3 blocks ==27022== total heap usage: 609 allocs, 606 frees, 19,877,073 bytes allocated ==27022== ==27022== 32 bytes in 1 blocks are still reachable in loss record 1 of 3 ==27022== at 0x4A08121: calloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so) ==27022== by 0x3A1A60168F: _dlerror_run (in /usr/lib64/libdl-2.17.so) ==27022== by 0x3A1A601197: dlsym (in /usr/lib64/libdl-2.17.so) ==27022== by 0x3A9D8A796D: ??? (in /usr/lib64/nvidia/libGL.so.331.67) ==27022== by 0x3A9DAE965F: ??? (in /usr/lib64/nvidia/libGL.so.331.67) ==27022== by 0x3A9DB1CB1F: ??? ==27022== by 0x3A9D8CD36A: ??? (in /usr/lib64/nvidia/libGL.so.331.67) ==27022== ==27022== 83 bytes in 1 blocks are still reachable in loss record 2 of 3 ==27022== at 0x4A06409: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so) ==27022== by 0x3A1A2863F9: strdup (in /usr/lib64/libc-2.17.so) ==27022== by 0x3A9D8A964E: ??? (in /usr/lib64/nvidia/libGL.so.331.67) ==27022== by 0x6578652F32322F: ??? ==27022== ==27022== 6,024 bytes in 1 blocks are definitely lost in loss record 3 of 3 ==27022== at 0x4A08121: calloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so) ==27022== by 0x3A9D8C032E: ??? (in /usr/lib64/nvidia/libGL.so.331.67) ==27022== ==27022== LEAK SUMMARY: ==27022== definitely lost: 6,024 bytes in 1 blocks ==27022== indirectly lost: 0 bytes in 0 blocks ==27022== possibly lost: 0 bytes in 0 blocks ==27022== still reachable: 115 bytes in 2 blocks ==27022== suppressed: 0 bytes in 0 blocks These do not seem to be related to my library. Should I be concerned about theses warnings? Or should I be making an attempt to suppress these leaks? If I should suppress what would be the cleanest way to do this from a Makefile?
It is hard to say whether you should suppress them or not, but if you are certain that your library is clean, you can generate a suppression file. You can then call Valgrind with the "--suppressions" flag. If the name of your suppression file is suppfile: > valgrind --suppressions=suppfile ./program If you are executing valgrind from a Makefile, add the suppressions flag to the valgrind command. You can also create a default options file ".valgrindrc", which you put in the same directory as your Makefile. In this file, put any arguments you want.
how to check memory leaks in C++ Qt application on Linux?
I am debugging my C++ application with valgrind --leak-check=yes and I am getting a lot of information about possible memory leaks. This is C++ application that uses Qt, POSIX threads and QuantLib. I think the information is not correct and I have tested it and I got a lot of these info even if app is very simple Qt app that does nothing. Probably valgrind is misinterpreting memory info being confused about Qt and POSIX threads. My question is what can I do, how to debug this Qt app correctly, ideally using valgrind, but maybe different way if possible? ==9419== Memcheck, a memory error detector ==9419== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al. ==9419== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info ==9419== Command: ./qt_tradingclient_1 ==9419== Parent PID: 19797 ==9419== ==9419== ==9419== HEAP SUMMARY: ==9419== in use at exit: 1,587,688 bytes in 10,156 blocks ==9419== total heap usage: 365,203 allocs, 355,047 frees, 92,510,461 bytes allocated ==9419== ==9419== 1 bytes in 1 blocks are possibly lost in loss record 3 of 5,210 ==9419== at 0x4C2B3F8: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==9419== by 0x8AC36E0: g_malloc (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.3400.1) ==9419== by 0x8AD9F5B: g_strdup (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.3400.1) ==9419== by 0x88461DB: g_param_spec_string (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.3400.1) ==9419== by 0x1153F1B7: ??? (in /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.13) ==9419== by 0x8855925: g_type_class_ref (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.3400.1) ==9419== by 0x883DDF0: g_object_newv (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.3400.1) ==9419== by 0x883E38B: g_object_new (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.3400.1) ==9419== by 0x1153D7DF: gtk_settings_get_for_screen (in /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.13) ==9419== by 0x114EC298: ??? (in /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.13) ==9419== by 0x883A5C3: g_cclosure_marshal_VOID__OBJECTv (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.3400.1) ==9419== by 0x8837406: ??? (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.3400.1) ==9419== ==9419== 1 bytes in 1 blocks are possibly lost in loss record 4 of 5,210 ==9419== at 0x4C2B3F8: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==9419== by 0x8AC36E0: g_malloc (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.3400.1) ==9419== by 0x8AD9F5B: g_strdup (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.3400.1) ==9419== by 0x88461DB: g_param_spec_string (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.3400.1) ==9419== by 0x114E1933: ??? (in /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.13) ==9419== by 0x8855925: g_type_class_ref (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.3400.1) ==9419== by 0x170E3225: ??? (in /usr/lib/x86_64-linux-gnu/gtk-2.0/modules/libcanberra-gtk-module.so) ==9419== by 0x170E4FB1: gtk_module_init (in /usr/lib/x86_64-linux-gnu/gtk-2.0/modules/libcanberra-gtk-module.so) ==9419== by 0x114EB7F0: ??? (in /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.13) ==9419== by 0x883713F: g_closure_invoke (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.3400.1) ==9419== by 0x884854F: ??? (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.3400.1) ==9419== by 0x88504AE: g_signal_emit_valist (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.3400.1) ==9419== //and many more, and finally summary: ==9419== 32,768 bytes in 16 blocks are possibly lost in loss record 5,208 of 5,210 ==9419== at 0x4C2B4F0: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==9419== by 0x8AC377E: g_realloc (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.3400.1) ==9419== by 0x8A931C2: ??? (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.3400.1) ==9419== by 0x8A93632: g_array_insert_vals (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.3400.1) ==9419== by 0x1151B084: ??? (in /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.13) ==9419== by 0x1151B289: ??? (in /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.13) ==9419== by 0x16EBA76B: ??? (in /usr/lib/x86_64-linux-gnu/gtk-2.0/2.10.0/engines/libmurrine.so) ==9419== by 0x1151CBF0: ??? (in /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.13) ==9419== by 0x11521066: gtk_rc_get_style (in /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.13) ==9419== by 0x115F2BEF: ??? (in /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.13) ==9419== by 0x115F35BD: gtk_widget_realize (in /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.13) ==9419== by 0x115F4187: gtk_widget_set_parent (in /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.13) ==9419== ==9419== LEAK SUMMARY: ==9419== definitely lost: 5,759 bytes in 31 blocks ==9419== indirectly lost: 12,804 bytes in 396 blocks ==9419== possibly lost: 482,706 bytes in 2,236 blocks ==9419== still reachable: 1,086,419 bytes in 7,493 blocks ==9419== suppressed: 0 bytes in 0 blocks ==9419== Reachable blocks (those to which a pointer was found) are not shown. ==9419== To see them, rerun with: --leak-check=full --show-reachable=yes ==9419== ==9419== For counts of detected and suppressed errors, rerun with: -v ==9419== ERROR SUMMARY: 812 errors from 812 contexts (suppressed: 3 from 3)
If you are sure that your application is leaking memory but it is not detected in Valgrind, then perhaps Velgrind is finding some problem to load your application. If you are not sure, then it is possible that the library you are using leaks memory and it should be Ok.