2

I have been chasing a memory problem in my program that links against -lcairo and -lX11. Finally, I decided to comment out all lines in my main() and make sure that valgrind is happy. To my surprise, it is not:

==7570== Memcheck, a memory error detector
==7570== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==7570== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==7570== Command: ./Test
==7570== 
==7570== 
==7570== HEAP SUMMARY:
==7570==     in use at exit: 10,360 bytes in 5 blocks
==7570==   total heap usage: 5 allocs, 0 frees, 10,360 bytes allocated
==7570== 
==7570== 2,072 bytes in 1 blocks are still reachable in loss record 1 of 5
==7570==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7570==    by 0x5FCCE9A: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
==7570==    by 0x5FCBACE: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
==7570==    by 0x5FCD585: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
==7570==    by 0x5F7F508: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
==7570==    by 0x4010139: call_init.part.0 (dl-init.c:78)
==7570==    by 0x4010222: _dl_init (dl-init.c:36)
==7570==    by 0x4001309: ??? (in /lib/x86_64-linux-gnu/ld-2.19.so)
==7570== 
==7570== 2,072 bytes in 1 blocks are still reachable in loss record 2 of 5
==7570==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7570==    by 0x5FCCE9A: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
==7570==    by 0x5FCA61F: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
==7570==    by 0x5FCD5A0: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
==7570==    by 0x5F7F508: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
==7570==    by 0x4010139: call_init.part.0 (dl-init.c:78)
==7570==    by 0x4010222: _dl_init (dl-init.c:36)
==7570==    by 0x4001309: ??? (in /lib/x86_64-linux-gnu/ld-2.19.so)
==7570== 
==7570== 2,072 bytes in 1 blocks are still reachable in loss record 3 of 5
==7570==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7570==    by 0x5FCCE9A: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
==7570==    by 0x5FE5A8F: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
==7570==    by 0x5FBC1A5: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
==7570==    by 0x5FCD5AB: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
==7570==    by 0x5F7F508: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
==7570==    by 0x4010139: call_init.part.0 (dl-init.c:78)
==7570==    by 0x4010222: _dl_init (dl-init.c:36)
==7570==    by 0x4001309: ??? (in /lib/x86_64-linux-gnu/ld-2.19.so)
==7570== 
==7570== 2,072 bytes in 1 blocks are still reachable in loss record 4 of 5
==7570==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7570==    by 0x5FCCE9A: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
==7570==    by 0x60053CF: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
==7570==    by 0x5FCD5AB: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
==7570==    by 0x5F7F508: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
==7570==    by 0x4010139: call_init.part.0 (dl-init.c:78)
==7570==    by 0x4010222: _dl_init (dl-init.c:36)
==7570==    by 0x4001309: ??? (in /lib/x86_64-linux-gnu/ld-2.19.so)
==7570== 
==7570== 2,072 bytes in 1 blocks are still reachable in loss record 5 of 5
==7570==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7570==    by 0x5FCCE9A: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
==7570==    by 0x5FCFCBF: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
==7570==    by 0x5F7F508: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
==7570==    by 0x4010139: call_init.part.0 (dl-init.c:78)
==7570==    by 0x4010222: _dl_init (dl-init.c:36)
==7570==    by 0x4001309: ??? (in /lib/x86_64-linux-gnu/ld-2.19.so)
==7570== 
==7570== LEAK SUMMARY:
==7570==    definitely lost: 0 bytes in 0 blocks
==7570==    indirectly lost: 0 bytes in 0 blocks
==7570==      possibly lost: 0 bytes in 0 blocks
==7570==    still reachable: 10,360 bytes in 5 blocks
==7570==         suppressed: 0 bytes in 0 blocks
==7570== 
==7570== For counts of detected and suppressed errors, rerun with: -v
==7570== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

Can a program with an empty main() allocate memory and end up with some reachable blocks? Is there a way to get rid of this strange problem?

AlwaysLearning
  • 7,257
  • 4
  • 33
  • 68
  • 2
    There could be static objects in libraries you're linking against. You'll just have to make a note of this report and discount those entries when looking for leaks with the real code. – M.M Nov 22 '15 at 21:17
  • Right. Is there a known solution in the case of this particular library, i.e. `pixman`? – AlwaysLearning Nov 22 '15 at 21:21
  • I don't know. If it's open-source you could try building it yourself and investigating. – M.M Nov 22 '15 at 21:22

1 Answers1

2

Yes. It is possible.

One way is that there might be some static objects in the libraries you are linking against. This has already been pointed out by @M.M

The other way is that if you are linking against shared libraries, with no static objects, and certain functions in such a library uses __attribute__((constructor)) . This attribute causes these functions to execute before main() (works only with gcc), and hence you see memory allocations. These functions are chiefly employed by libraries to declare certain attributes about their functions if they are used in your program. For more details about these attributes you can refer to :

http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html

Ujjwal Aryan
  • 3,827
  • 3
  • 20
  • 31
  • Thank you. This is enlightening. However, it also sounds like the only way to deal with the problem is to get deeply into the source code of `pixman`, which I am not eager to do. I would very much appreciate if someone who actually uses `pixman` (directly or indirectly, such as by linking against `Cairo`) could shed light on the correct usage that results in a clean slate. – AlwaysLearning Nov 22 '15 at 21:41
  • Though I do not use pixman, usually removing that attribute does not do a huge amount of damage as it chiefly aims for compiler optimization. Removing __attribute__((constructor)), usually does not affect the results, but simply results in poorer compiler optimization. If the library is designed for use with non-GCC compilers also, then u can use the library without gcc, which will not result in any overhead owing to those attributes.Static objects are difficult to avoid ,as they are mostly inherent to the underlying algorithm. The exact answer requires thorough study of pixman – Ujjwal Aryan Nov 22 '15 at 21:59