In my OpenSSL client I have the problem that the very moment I chose to link libeay32 and ssleay32 statically instead of dynamically I got tons of memory leak errors from Visual Leak Detector. I copied the commands from the OP in this thread, but I still had 6 left. Then I added sk_SSL_COMP_free(SSL_COMP_get_compression_methods());
as advised by 4LegsDrivenCat in the same thread and only 4 more were left, all of which are apparently related to loading a trusted certificate which I use to compare to the server's certificate.
I use Visual Studio 2013 Express, OpenSSL 1.0.1L (both 32 and 64 Bit), VLD 2.4RC2 and my PC is Windows 7 64 Bit.
The callstack below is 64 Bit from VLD in safe mode. In 32 Bit VLD crashed in safe mode (while it works in fast mode but doesn't yield a decent callstack). I removed the parts of the callstack that referred to my own functions as well as the hex-data.
Visual Leak Detector Version 2.4RC2 installed.
WARNING: Visual Leak Detector detected memory leaks!
---------- Block 5671 at 0x000000000097E9B0: 180 bytes ----------
Leak Hash: 0xA14DA3AA, Count: 1, Total 180 bytes
Call Stack (TID 7088):
0x000000007746FAC0 (File and line number not available): ntdll.dll!RtlAllocateHeap
f:\dd\vctools\crt\crtw32\heap\malloc.c (58): MyLib.dll!_heap_alloc_base
f:\dd\vctools\crt\crtw32\misc\dbgheap.c (431): MyLib.dll!_heap_alloc_dbg_impl + 0xA bytes
f:\dd\vctools\crt\crtw32\misc\dbgheap.c (239): MyLib.dll!_nh_malloc_dbg_impl + 0x22 bytes
f:\dd\vctools\crt\crtw32\misc\dbgheap.c (302): MyLib.dll!_nh_malloc_dbg + 0x2A bytes
f:\dd\vctools\crt\crtw32\misc\dbgmalloc.c (56): MyLib.dll!malloc + 0x21 bytes
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\mem.c (312): MyLib.dll!CRYPTO_malloc + 0xF bytes
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\lhash\lhash.c (121): MyLib.dll!lh_new + 0x16 bytes
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\err\err.c (450): MyLib.dll!int_thread_get + 0x13 bytes
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\err\err.c (509): MyLib.dll!int_thread_set_item + 0xF bytes
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\err\err.c (1031): MyLib.dll!ERR_get_state
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\err\err.c (730): MyLib.dll!ERR_put_error + 0x5 bytes
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\pem\pem_lib.c (703): MyLib.dll!PEM_read_bio + 0x20 bytes
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\pem\pem_info.c (280): MyLib.dll!PEM_X509_INFO_read_bio + 0x10 bytes
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\x509\by_file.c (278): MyLib.dll!X509_load_cert_crl_file
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\x509\by_file.c (123): MyLib.dll!by_file_ctrl
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\x509\x509_lu.c (120): MyLib.dll!X509_LOOKUP_ctrl
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\x509\x509_d2.c (92): MyLib.dll!X509_STORE_load_locations + 0x1D bytes
---------- Block 5670 at 0x000000001AC815C0: 164 bytes ----------
Leak Hash: 0x38C8916E, Count: 1, Total 164 bytes
Call Stack (TID 7088):
0x000000007746FAC0 (File and line number not available): ntdll.dll!RtlAllocateHeap
f:\dd\vctools\crt\crtw32\heap\malloc.c (58): MyLib.dll!_heap_alloc_base
f:\dd\vctools\crt\crtw32\misc\dbgheap.c (431): MyLib.dll!_heap_alloc_dbg_impl + 0xA bytes
f:\dd\vctools\crt\crtw32\misc\dbgheap.c (239): MyLib.dll!_nh_malloc_dbg_impl + 0x22 bytes
f:\dd\vctools\crt\crtw32\misc\dbgheap.c (302): MyLib.dll!_nh_malloc_dbg + 0x2A bytes
f:\dd\vctools\crt\crtw32\misc\dbgmalloc.c (56): MyLib.dll!malloc + 0x21 bytes
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\mem.c (312): MyLib.dll!CRYPTO_malloc + 0xF bytes
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\lhash\lhash.c (119): MyLib.dll!lh_new + 0x13 bytes
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\err\err.c (450): MyLib.dll!int_thread_get + 0x13 bytes
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\err\err.c (509): MyLib.dll!int_thread_set_item + 0xF bytes
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\err\err.c (1031): MyLib.dll!ERR_get_state
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\err\err.c (730): MyLib.dll!ERR_put_error + 0x5 bytes
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\pem\pem_lib.c (703): MyLib.dll!PEM_read_bio + 0x20 bytes
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\pem\pem_info.c (280): MyLib.dll!PEM_X509_INFO_read_bio + 0x10 bytes
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\x509\by_file.c (278): MyLib.dll!X509_load_cert_crl_file
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\x509\by_file.c (123): MyLib.dll!by_file_ctrl
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\x509\x509_lu.c (120): MyLib.dll!X509_LOOKUP_ctrl
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\x509\x509_d2.c (92): MyLib.dll!X509_STORE_load_locations + 0x1D bytes
---------- Block 5669 at 0x000000001ADABE80: 588 bytes ----------
Leak Hash: 0xC3E47B0F, Count: 1, Total 588 bytes
Call Stack (TID 7088):
0x000000007746FAC0 (File and line number not available): ntdll.dll!RtlAllocateHeap
f:\dd\vctools\crt\crtw32\heap\malloc.c (58): MyLib.dll!_heap_alloc_base
f:\dd\vctools\crt\crtw32\misc\dbgheap.c (431): MyLib.dll!_heap_alloc_dbg_impl + 0xA bytes
f:\dd\vctools\crt\crtw32\misc\dbgheap.c (239): MyLib.dll!_nh_malloc_dbg_impl + 0x22 bytes
f:\dd\vctools\crt\crtw32\misc\dbgheap.c (302): MyLib.dll!_nh_malloc_dbg + 0x2A bytes
f:\dd\vctools\crt\crtw32\misc\dbgmalloc.c (56): MyLib.dll!malloc + 0x21 bytes
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\mem.c (312): MyLib.dll!CRYPTO_malloc + 0xF bytes
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\err\err.c (1019): MyLib.dll!ERR_get_state + 0x17 bytes
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\err\err.c (730): MyLib.dll!ERR_put_error + 0x5 bytes
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\pem\pem_lib.c (703): MyLib.dll!PEM_read_bio + 0x20 bytes
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\pem\pem_info.c (280): MyLib.dll!PEM_X509_INFO_read_bio + 0x10 bytes
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\x509\by_file.c (278): MyLib.dll!X509_load_cert_crl_file
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\x509\by_file.c (123): MyLib.dll!by_file_ctrl
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\x509\x509_lu.c (120): MyLib.dll!X509_LOOKUP_ctrl
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\x509\x509_d2.c (92): MyLib.dll!X509_STORE_load_locations + 0x1D bytes
---------- Block 5672 at 0x000000001ADC4180: 76 bytes ----------
Leak Hash: 0x02B2EA5E, Count: 1, Total 76 bytes
Call Stack (TID 7088):
0x000000007746FAC0 (File and line number not available): ntdll.dll!RtlAllocateHeap
f:\dd\vctools\crt\crtw32\heap\malloc.c (58): MyLib.dll!_heap_alloc_base
f:\dd\vctools\crt\crtw32\misc\dbgheap.c (431): MyLib.dll!_heap_alloc_dbg_impl + 0xA bytes
f:\dd\vctools\crt\crtw32\misc\dbgheap.c (239): MyLib.dll!_nh_malloc_dbg_impl + 0x22 bytes
f:\dd\vctools\crt\crtw32\misc\dbgheap.c (302): MyLib.dll!_nh_malloc_dbg + 0x2A bytes
f:\dd\vctools\crt\crtw32\misc\dbgmalloc.c (56): MyLib.dll!malloc + 0x21 bytes
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\mem.c (312): MyLib.dll!CRYPTO_malloc + 0xF bytes
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\lhash\lhash.c (193): MyLib.dll!lh_insert + 0x15 bytes
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\err\err.c (515): MyLib.dll!int_thread_set_item
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\err\err.c (1031): MyLib.dll!ERR_get_state
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\err\err.c (730): MyLib.dll!ERR_put_error + 0x5 bytes
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\pem\pem_lib.c (703): MyLib.dll!PEM_read_bio + 0x20 bytes
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\pem\pem_info.c (280): MyLib.dll!PEM_X509_INFO_read_bio + 0x10 bytes
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\x509\by_file.c (278): MyLib.dll!X509_load_cert_crl_file
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\x509\by_file.c (123): MyLib.dll!by_file_ctrl
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\x509\x509_lu.c (120): MyLib.dll!X509_LOOKUP_ctrl
d:\cfiles\projects\winssl\openssl-1.0.1l\crypto\x509\x509_d2.c (92): MyLib.dll!X509_STORE_load_locations + 0x1D bytes
Visual Leak Detector detected 4 memory leaks (1008 bytes).
Largest number used: 529114 bytes.
Total allocations: 1070421 bytes.
Visual Leak Detector is now exiting.
edit: I pinned the leaks down to the call to SSL_CTX_load_verify_locations. Does anyone know what I need to de-allocate when using this function? Just commenting this function causes the leaks to disappear, so it's not because of the parameters I pass to it.
Latching on to this, it looks like some error state (or strings) needs to be free'd.
The code for startup and shutdown is shown below (including FIPS). If you do things like load DH parameters, then you will need to clean them up, too.
Dr. Henson was very helpful with his suggestion of calling
ERR_remove_state
for each thread. See Order of Cleanup to avoid memory leaks? on the OpenSSL mailing list.Startup
SSL_library_init();
SSL_load_error_strings();
FIPS_mode_set(1);
CRYPTO_set_id_callback(<fn>);
CRYPTO_set_locking_callback(<fn>);
Shutdown
FIPS_mode_set(0);
CRYPTO_set_locking_callback(NULL);
CRYPTO_set_id_callback(NULL);
ENGINE_cleanup();
CONF_modules_unload();
ERR_free_strings();
EVP_cleanup();
CRYPTO_cleanup_all_ex_data();
And, for each thread:
ERR_remove_state();
You only need
CRYPTO_set_id_callback
andCRYPTO_set_locking_callback
if your program is multi-threaded. See the Openssl threads(3) man page.I believe you can call
SSL_COMP_free_compression_methods
in OpenSSL 1.0.2 and above. That addresses some of the complaint below. But its not available in OpenSSL 1.0.1 and below.Yeah, this causes a leak. Its well known and due to
ssl_comp_methods
being lazily allocated but never freed. See OpenSSL Issue 2561: Memory leak with SSL built-in compressions.Some of the OpenSSL devs don't feel its worth their time to fix it. See Small memory leak on multithreaded server on the OpenSSL mailing list.
The following is one of the dev's position on it:
And here's another thread about that particular leak: Preferred way to free ssl_comp_methods?. And here's that same dev's response:
What he failed to realize is Java and .Net will load/unload the library many times during a program's lifecycle, so that small amount of "who cares" can grow unbounded.
When he was told about the alternate use case, here was his reply. I guess, he is suggesting that Oracle and Java re-architect their languages. Or don't use OpenSSL in them.
Here was the response of one of the folks who maintain a Java VM:
Here a section on fixing the
ssl_comp_methods
leak.In all cases, you will need to add the patch described below.
For a program to do it manually, just add a function named
free_compressions
(or similar) and call it on shutdown like all the other methods listed above. The function needs to be exported.To do it automatically under Linux, its takes a little trickery. You have to use a GCC extension:
__attribute__ ((destructor))
.To do it automatically under Windows, you have to do it in
DllMain
. But you have to be careful about what you do inDllMain
, and how you do it. So maybe something like:-----
Looking at the close reason (which you can't do at the moment), the close vote was cast with the reason:
Normally that applies. But in your case it does not; and its not readily apparent to those not familiar with the issue. In fact, you could write a simple program that just initializes and then unitializes the library and it will probably leak...
As a matter of policy, the site can't make a rule "Always provide relevant code except for some OpenSSL memory leaks" (which is effectively what we need to handle your case).
Small addition to jww post, if your OpenSSL version is built with zlib library then you should add COMP_zlib_cleanup(); to shutdown section. Because its DSO module is not freed by default. So, full shutdown code should be: