1

If you create a program with just the following two lines:

PGconn *conn = PQconnectdb("user=dbtest password=dbtest dbname=testdb host=localhost port=5432");
PQfinish(conn);

And run it through valgrind like so:

valgrind --leak-check=full --show-leak-kinds=all ./program

You see this:

==25388== Memcheck, a memory error detector
==25388== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==25388== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==25388== Command: ./program
==25388== 
==25388== 
==25388== HEAP SUMMARY:
==25388==     in use at exit: 109 bytes in 2 blocks
==25388==   total heap usage: 6,948 allocs, 6,946 frees, 666,147 bytes allocated
==25388== 
==25388== 13 bytes in 1 blocks are still reachable in loss record 1 of 2
==25388==    at 0x483874F: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==25388==    by 0x4CB0635: CRYPTO_strdup (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1)
==25388==    by 0x4BD8AFB: BIO_meth_new (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1)
==25388==    by 0x488BE8B: ??? (in /usr/lib/x86_64-linux-gnu/libpq.so.5.11)
==25388==    by 0x488D19C: ??? (in /usr/lib/x86_64-linux-gnu/libpq.so.5.11)
==25388==    by 0x487507F: PQconnectPoll (in /usr/lib/x86_64-linux-gnu/libpq.so.5.11)
==25388==    by 0x4875E3E: ??? (in /usr/lib/x86_64-linux-gnu/libpq.so.5.11)
==25388==    by 0x4878CD7: PQconnectdb (in /usr/lib/x86_64-linux-gnu/libpq.so.5.11)
==25388==    by 0x109158: main (in /workspace/test/src/program)
==25388== 
==25388== 96 bytes in 1 blocks are still reachable in loss record 2 of 2
==25388==    at 0x483874F: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==25388==    by 0x4CA70E8: CRYPTO_zalloc (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1)
==25388==    by 0x4BD8ADF: BIO_meth_new (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1)
==25388==    by 0x488BE8B: ??? (in /usr/lib/x86_64-linux-gnu/libpq.so.5.11)
==25388==    by 0x488D19C: ??? (in /usr/lib/x86_64-linux-gnu/libpq.so.5.11)
==25388==    by 0x487507F: PQconnectPoll (in /usr/lib/x86_64-linux-gnu/libpq.so.5.11)
==25388==    by 0x4875E3E: ??? (in /usr/lib/x86_64-linux-gnu/libpq.so.5.11)
==25388==    by 0x4878CD7: PQconnectdb (in /usr/lib/x86_64-linux-gnu/libpq.so.5.11)
==25388==    by 0x109158: main (in /workspace/test/src/program)
==25388== 
==25388== LEAK SUMMARY:
==25388==    definitely lost: 0 bytes in 0 blocks
==25388==    indirectly lost: 0 bytes in 0 blocks
==25388==      possibly lost: 0 bytes in 0 blocks
==25388==    still reachable: 109 bytes in 2 blocks
==25388==         suppressed: 0 bytes in 0 blocks
==25388== 
==25388== For counts of detected and suppressed errors, rerun with: -v
==25388== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

I noticed that opening and closing more connections doesn't seem to affect the amount of bytes lost or still reachable.

I'm not very familiar with C, so I have to ask:

How come there's bytes still reachable? I would expect everything to be deallocated when I close the connection to the database.

I_cannot_C
  • 23
  • 4
  • Nothing is lost here, `still reachable` is perfectly fine. You should only care about `definitely lost` and `indirectly lost`. `possibly lost` is also usually a false alarm. – Kiril Kirov Sep 10 '19 at 17:16
  • @KirilKirov It might be fine, but I'd like to know how come that number's more than zero. As far as I can tell, everything allocated should have been deallocated. – I_cannot_C Sep 10 '19 at 17:32

1 Answers1

1

Those allocations were performed during the initialisation of libcrypto, which is used by the postgresql client in order to communicate with the server via SSL/TLS. That initialisation is only done once; it doesn't matter how many connections you open. (However, if the connections use different cyphers, there may be additional initialisations.)

Libcrypto does provide interfaces which can be used to free storage allocated during initialisation. These are documented in the OpenSSL documentation. So you could try adding them to your code. But, honestly, it really doesn't matter except to make the valgrind report clearer.

rici
  • 234,347
  • 28
  • 237
  • 341
  • It would matter to apply that as a bug fix into libpq directly, wouldn't it? In any case application A should not try to fix issues that are in its library B that uses library C "not completely clean" - because application A is likely not linked to lib C and if it works around B's bugs then it is buggy as soon as B fixes its use of C. For this case: opening an issue with B and use [valgrind suppressions](https://valgrind.org/docs/manual/manual-core.html#manual-core.suppress) seems the way to go. – Simon Sobisch Feb 02 '22 at 12:39