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.
Related
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).
My code is allocating memory and never freeing it, even though it should (at least in my opinion).
The header looks like this:
typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> sslSocket_t;
class Object {
boost::asio::io_service ioService_;
boost::asio::ip::tcp::acceptor acceptor_;
boost::asio::ssl::context context_;
void functionOne();
void functionTwo(shared_ptr<sslSocket_t>& sslSocket, const boost::system::error_code& error)
}
And my source like this:
void Object::functionOne() {
for (int i = 0; i < 10; i++) {
shared_ptr<sslSocket_t> sslSocket(new sslSocket_t(ioService_, context_));
acceptor_.async_accept(sslSocket->lowest_layer(),
boost::bind(&Object::functionTwo, this, sslSocket, boost::asio::placeholders::error));
}
acceptor_.cancel();
boost::asio::io_service::work work(ioService_);
ioService_.run();
}
void functionTwo(shared_ptr<sslSocket_t>& sslSocket, const boost::system::error_code& err) {
// Do nothing
}
So when i call Object.functionOne(), memory is getting allocated to the Object.ioService_ object, in order to be able to call the bound asynchronous method. Then after the loop, all pending asynchronous actions on the acceptor are getting canceled. The appropriate handler is getting invoked as soon as Object.ioService_.run() is called (i've been testing that). BUT for some reason, the allocated memory does not get freed. So can someone please explain, why the memory is not getting deallocated and give me a hint how to free it?
Btw.: I'm working on debian and looking at /proc/self/status -> VmRSS to whatch the used memory.
#Vinnie Falco
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/bind.hpp>
#include <iostream>
#include <memory>
typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> sslSocket_t;
using namespace std;
struct T {
boost::asio::io_service ioService_;
boost::asio::ip::tcp::acceptor acceptor_;
boost::asio::ssl::context context_;
void functionOne() {
for (int i = 0; i < 10; i++) {
shared_ptr<sslSocket_t> sslSocket(new sslSocket_t(ioService_, context_));
acceptor_.async_accept(sslSocket->lowest_layer(),
boost::bind(&T::functionTwo, this, sslSocket, boost::asio::placeholders::error));
}
acceptor_.cancel();
boost::asio::io_service::work work(ioService_);
ioService_.run();
}
void functionTwo(shared_ptr<sslSocket_t>& sslSocket, const boost::system::error_code& err) {
// Do nothing
}
T() : acceptor_(ioService_,
boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), 443)),
context_(boost::asio::ssl::context::sslv23_server) {
}
~T() {
}
};
int main() {
try {
T t;
t.functionOne();
} catch (std::exception& e) {
cout << "Exception: " << e.what() << endl;
}
}
My question is not, if and why the destructor of T is called, this works as supposed to. But the behaviour concerning the used memory is strange.
So if you increase the limit in the for loop, you will observe, that a lot of memory is getting reserved by the program, even though it should be released after all asnchronous handlers have been invoked. But the sslSocket objects are not getting deallocated, which is what my question is about: Why is the memory (specifically the memory allocated for the sslSocket), bound to the functor functionTwo, not deallocated, even after the asynchronous method fucntionTwo has been invoked and no reference to the sslSocket is left?
My final approach to explain my concern (edit 28 April)
Alright, i made a runnable example, that shows my concern:
My Problem in an example
Output:
Before leaking call: 6984 kB
Asynchronous calls of functionTwo: 10000
Memory while ioService is still running: 460244 kB
Memory after ioService is stopped: 460244 kB
What's even more crazy is, that in my own local implementation I get the following output:
Memory leaking call: 8352 kB
Asynchronous calls of functionTwo: 10000
Memory while ioService is still running: 471932 kB
Memory after ioService is stopped: 8436 kB
So it can clearly be seen: the memory is not freed, even after all asynchronous operations have been invoked.
Summary and understood(?) behaviour (last edit)
As some of you might have missunderstood, i'm not thinking that there is some kind of a leak in my code. I named the structure in my code example Leak, which might have confused you, but my question is not if and where a memory leak occurs in my example. It's about the memory allocation in combination with the ioService object. First I thought, that the claimed memory is increasing infinitly. I made a last approach to understand this behaviour and came to the conclusion, that the memory management is fine. Memory is not reclaimed by the OS, but the program's memory allocation is converging to a limit, which is fine with me. So this problem is out of my way.
Example: Converging memory consumption
What disturbed me most was that my local implemention showed a slightly different behaviour. There the memory was reclaimed by the OS, when the ioService object was done with its jobs and reset, which satisfied my expectations.
So to sum up all observations:
The allocated memory is managed by the C++ Runtime and the OS. It's quite difficult (if not even impossible?) to directly observe the allocation procedure, since it's optimized to reduce the amount of requests for new memory pages, which means that allocated and freed memory might not be immidiatly reallocated by the OS.
To point out the critical point to me with this behaviour, i want to describe the usage of my program: I'm developing a server application, which means, that the program should run an infinit amount of time. If the program claims a lot of peak memory at some time, it's totaly fine, but it needs to release the claimed memory at some point in runtime, not after the runtime. So to me, there is only one question remaining:
Will the claimed (but unused) memory be reclaimed by the OS at some time? Or do I have to manage the memory on my own (with new and delete) in runtime?
I'm not sure what the problem is but I think you're doing something wrong. Could you provide a self-contained example that exhibits the problem? This sample program compiles and runs, and the destructor is called:
#include <boost/asio.hpp>
#include <functional>
#include <iostream>
#include <memory>
struct T
{
T()
{
std::cerr << "T::T()\n";
}
~T()
{
std::cerr << "T::~T()\n";
}
};
void f(std::shared_ptr<T>&)
{
}
int main()
{
using namespace boost::asio;
io_service ios;
ios.post(std::bind(&f, std::make_shared<T>()));
ios.run();
}
You can see the output here: http://melpon.org/wandbox/permlink/0fkIAnoMXDOeedx7
The output:
T::T()
T::~T()
It took me a while, but i finally managed to work it out by myself.
So to clearify things, let's make sure, that the root of my problem is understood:
I'm developing a server application, which is meant to run for an infinit amount of time. This application must be able to handle a lot of concurrent incomming connections. At some point in time, there may be a peak in load, leading to a lot of claimed memory to my application. Then after a while, most incomming requests have been processed, causing a lot of objects to be freed in runtime. Since the OS is in no need for memory (My application is the only huge memory consumer on the server), all freed memory stays with my application and can be reused at another point in time. This would be absolutely fine with me, but some customers and administrators might misinterpret the greater amount of constantly claimed memory as a memory leaking application. To avoid this, i wanted to hand some of the unused memory back to the OS manually. In my example, the bound handlers to the ioService (e.g. accepting a new connection) would be freed in runtime, but the appropriate memory won't be reclaimed by the OS. So to do this manually, i found the following solution:
Release unused heap memory under Linux in C/C++: int malloc_trim(size_t pad)
The documentation can be found here. Simplified explained, this method releases unused memory from the heap to the OS, which is exactly what i've been searching for. I'm aware that under memory optimization aspects, the manual use of this function maybe dangerous, but since i only want to release the memory every few minutes, this performance issue is acceptable to me.
Thank you all for your efforts and patience!
Taking your selfcontained example and running it under valgrind shows that exactly nothing is leaked
==14098==
==14098== HEAP SUMMARY:
==14098== in use at exit: 73,696 bytes in 7 blocks
==14098== total heap usage: 163,524 allocs, 163,517 frees, 733,133,505 bytes allocated
==14098==
==14098== LEAK SUMMARY:
==14098== definitely lost: 0 bytes in 0 blocks
==14098== indirectly lost: 0 bytes in 0 blocks
==14098== possibly lost: 0 bytes in 0 blocks
==14098== still reachable: 73,696 bytes in 7 blocks
==14098== suppressed: 0 bytes in 0 blocks
==14098== Rerun with --leak-check=full to see details of leaked memory
If you supply valgrind --show-leak-kinds=all --leak-check=full ./test you'll find that the "leaked" (left-over reachables) are the usual static stuff allocated from libssl/libcrypto. They get allocated even if you only do 1 iteration. No change for 10000 iterations.
==14214== Memcheck, a memory error detector
==14214== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==14214== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==14214== Command: ./test 10000
==14214==
Before leaking call: 50056 kB
Asynchronous calls of functionTwo: 10000
Memory while ioService is still running: 265592 kB
Memory after ioService is stopped: 265592 kB
==14214==
==14214== HEAP SUMMARY:
==14214== in use at exit: 73,696 bytes in 7 blocks
==14214== total heap usage: 163,524 allocs, 163,517 frees, 733,133,505 bytes allocated
==14214==
==14214== 24 bytes in 1 blocks are still reachable in loss record 1 of 7
==14214== at 0x4C2BBCF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14214== by 0x5307E77: CRYPTO_malloc (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==14214== by 0x53BF315: lh_insert (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==14214== by 0x53C1863: ??? (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==14214== by 0x53C245D: ERR_get_state (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==14214== by 0x53C25EE: ERR_clear_error (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==14214== by 0x40C9CA: context (context.ipp:70)
==14214== by 0x40C9CA: Leak::Leak() (test.cpp:77)
==14214== by 0x403E13: main (test.cpp:86)
==14214==
==14214== 32 bytes in 1 blocks are still reachable in loss record 2 of 7
==14214== at 0x4C2BBCF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14214== by 0x5307E77: CRYPTO_malloc (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==14214== by 0x53BE7AE: sk_new (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==14214== by 0x507FD69: ??? (in /lib/x86_64-linux-gnu/libssl.so.1.0.0)
==14214== by 0x5081E68: SSL_COMP_get_compression_methods (in /lib/x86_64-linux-gnu/libssl.so.1.0.0)
==14214== by 0x5087532: SSL_library_init (in /lib/x86_64-linux-gnu/libssl.so.1.0.0)
==14214== by 0x40B9A8: do_init (openssl_init.ipp:39)
==14214== by 0x40B9A8: boost::asio::ssl::detail::openssl_init_base::instance() (openssl_init.ipp:131)
==14214== by 0x403C3C: openssl_init (openssl_init.hpp:60)
==14214== by 0x403C3C: __static_initialization_and_destruction_0 (openssl_init.hpp:90)
==14214== by 0x403C3C: _GLOBAL__sub_I_count (test.cpp:96)
==14214== by 0x40FE1C: __libc_csu_init (in /home/sehe/Projects/stackoverflow/test)
==14214== by 0x5EC09CE: (below main) (libc-start.c:245)
==14214==
==14214== 32 bytes in 1 blocks are still reachable in loss record 3 of 7
==14214== at 0x4C2BBCF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14214== by 0x5307E77: CRYPTO_malloc (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==14214== by 0x53BE7CC: sk_new (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==14214== by 0x507FD69: ??? (in /lib/x86_64-linux-gnu/libssl.so.1.0.0)
==14214== by 0x5081E68: SSL_COMP_get_compression_methods (in /lib/x86_64-linux-gnu/libssl.so.1.0.0)
==14214== by 0x5087532: SSL_library_init (in /lib/x86_64-linux-gnu/libssl.so.1.0.0)
==14214== by 0x40B9A8: do_init (openssl_init.ipp:39)
==14214== by 0x40B9A8: boost::asio::ssl::detail::openssl_init_base::instance() (openssl_init.ipp:131)
==14214== by 0x403C3C: openssl_init (openssl_init.hpp:60)
==14214== by 0x403C3C: __static_initialization_and_destruction_0 (openssl_init.hpp:90)
==14214== by 0x403C3C: _GLOBAL__sub_I_count (test.cpp:96)
==14214== by 0x40FE1C: __libc_csu_init (in /home/sehe/Projects/stackoverflow/test)
==14214== by 0x5EC09CE: (below main) (libc-start.c:245)
==14214==
==14214== 128 bytes in 1 blocks are still reachable in loss record 4 of 7
==14214== at 0x4C2BBCF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14214== by 0x5307E77: CRYPTO_malloc (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==14214== by 0x53BEFE1: lh_new (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==14214== by 0x53C1512: ??? (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==14214== by 0x53C182F: ??? (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==14214== by 0x53C245D: ERR_get_state (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==14214== by 0x53C25EE: ERR_clear_error (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==14214== by 0x40C9CA: context (context.ipp:70)
==14214== by 0x40C9CA: Leak::Leak() (test.cpp:77)
==14214== by 0x403E13: main (test.cpp:86)
==14214==
==14214== 176 bytes in 1 blocks are still reachable in loss record 5 of 7
==14214== at 0x4C2BBCF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14214== by 0x5307E77: CRYPTO_malloc (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==14214== by 0x53BEFBF: lh_new (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==14214== by 0x53C1512: ??? (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==14214== by 0x53C182F: ??? (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==14214== by 0x53C245D: ERR_get_state (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==14214== by 0x53C25EE: ERR_clear_error (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==14214== by 0x40C9CA: context (context.ipp:70)
==14214== by 0x40C9CA: Leak::Leak() (test.cpp:77)
==14214== by 0x403E13: main (test.cpp:86)
==14214==
==14214== 600 bytes in 1 blocks are still reachable in loss record 6 of 7
==14214== at 0x4C2BBCF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14214== by 0x5307E77: CRYPTO_malloc (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==14214== by 0x53C23F5: ERR_get_state (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==14214== by 0x53C25EE: ERR_clear_error (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==14214== by 0x40C9CA: context (context.ipp:70)
==14214== by 0x40C9CA: Leak::Leak() (test.cpp:77)
==14214== by 0x403E13: main (test.cpp:86)
==14214==
==14214== 72,704 bytes in 1 blocks are still reachable in loss record 7 of 7
==14214== at 0x4C2BBCF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14214== by 0x57731FF: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==14214== by 0x4010609: call_init.part.0 (dl-init.c:72)
==14214== by 0x401071A: call_init (dl-init.c:30)
==14214== by 0x401071A: _dl_init (dl-init.c:120)
==14214== by 0x4000D09: ??? (in /lib/x86_64-linux-gnu/ld-2.21.so)
==14214== by 0x1: ???
==14214== by 0xFFEFFFF76: ???
==14214== by 0xFFEFFFF7D: ???
==14214==
==14214== LEAK SUMMARY:
==14214== definitely lost: 0 bytes in 0 blocks
==14214== indirectly lost: 0 bytes in 0 blocks
==14214== possibly lost: 0 bytes in 0 blocks
==14214== still reachable: 73,696 bytes in 7 blocks
==14214== suppressed: 0 bytes in 0 blocks
==14214==
==14214== For counts of detected and suppressed errors, rerun with: -v
==14214== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Your way of measuring memory usage is not sound.
I think your approach is broken. You should never interleave async operations with asio. If your do all sorts of undefined crap will happen. The way you normally implement async accept is as follows:
void do_accept() {
shared_ptr<sslSocket_t> socket(new sslSocket_t(ioService_, context_));
// Queue an async accept operation
acceptor_.async_accept(socket->lowest_layer(), [this, socket](auto ec) {
if (!ec) {
// Handle the socket
}
// If not shutting down
this->do_accept(); // next accept
});
}
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.
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.
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.