Hello. There is a handy tool called Dr. Memory, which I have been using to check for memory leaks in programs I develop with MSYS2 and mingw-w64:
http://www.drmemory.org/ I noticed that it always reports a small memory leak for the application I was debugging. It's not a big deal, but it was kind of annoying so I am trying to figure out what is wrong. After a lot of debugging, I figured out that any variable using thread-local storage (__thread) is reported as a memory leak if the program uses it in any way. Here is a simple program I used to reproduce the error: #include <stdio.h> static __thread int foo; int main(int argc, char * const argv[]) { printf("%d %p\n", sizeof(foo), &foo); return 0; } This is the version of GCC I am using: $ gcc -v Using built-in specs. COLLECT_GCC=C:\msys64\mingw32\bin\gcc.exe COLLECT_LTO_WRAPPER=C:/msys64/mingw32/lib/gcc/i686-w64-mingw32/4.9.2/lto-wrapper.exe Target: i686-w64-mingw32 Configured with: ../gcc-4.9.2/configure --prefix=/mingw32 --with-local-prefix=/mingw32/local --build=i686-w64-mingw32 --host=i686-w64-mingw32 --target=i686-w64-mingw32 --with-native-system-header-dir=/mingw32/i686-w64-mingw32/include --libexecdir=/mingw32/lib --with-gxx-include-dir=/mingw32/include/c++/4.9.2 --enable-bootstrap --with-arch=i686 --with-tune=generic --enable-languages=c,lto,c++,objc,obj-c++,fortran,ada --enable-shared --enable-static --enable-libatomic --enable-threads=posix --enable-graphite --enable-fully-dynamic-string --enable-libstdcxx-time=yes --disable-libstdcxx-pch --disable-libstdcxx-debug --enable-cloog-backend=isl --enable-version-specific-runtime-libs --disable-cloog-version-check --disable-isl-version-check --enable-lto --enable-libgomp --disable-multilib --enable-checking=release --disable-rpath --disable-win32-registry --disable-nls --disable-werror --disable-symvers --with-libiconv --with-system-zlib --with-gmp=/mingw32 --with-mpfr=/mingw32 --with- mpc=/mingw32 --with-isl=/mingw32 --with-cloog=/mingw32 --with-pkgversion='Rev5, Built by MSYS2 project' --with-bugurl=http://sourceforge.net/projects/msys2 --with-gnu-as --with-gnu-ld --disable-sjlj-exceptions --with-dwarf2 Thread model: posix gcc version 4.9.2 (Rev5, Built by MSYS2 project) I compiled it and tested it like this: gcc -g bug.c -o bug.exe && drmemory -leaks_only bug.exe And Dr. Memory reported this leak, which goes away if I remove the line that accesses the address of the thread local variable: Error #1: POSSIBLE LEAK 8 direct bytes 0x00d30898-0x00d308a0 + 0 indirect bytes # 0 replace_malloc [d:\drmemory_package\common\alloc_replace.c:2377] # 1 libwinpthread-1.dll!? +0x0 (0x64b4466c <libwinpthread-1.dll+0x466c>) # 2 KERNELBASE.dll!WaitForSingleObjectEx+0xb6 (0x76a12cc7 <KERNELBASE.dll+0x2cc7>) # 3 KERNELBASE.dll!WaitForSingleObjectEx+0xd7 (0x76a12ce8 <KERNELBASE.dll+0x2ce8>) # 4 libwinpthread-1.dll!? +0x0 (0x64b44db3 <libwinpthread-1.dll+0x4db3>) # 5 libwinpthread-1.dll!? +0x0 (0x64b4466c <libwinpthread-1.dll+0x466c>) # 6 libwinpthread-1.dll!? +0x0 (0x64b4cd42 <libwinpthread-1.dll+0xcd42>) # 7 __emutls_get_address [C:/repo/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/crt/pesect.c:230] # 8 main [C:\Users\David\Documents\bugs\mingw_leak/bug.c:7] Interestingly, if I compile with g++ instead of GCC, the stack trace looks different: Error #1: POSSIBLE LEAK 8 direct bytes 0x00d405b0-0x00d405b8 + 0 indirect bytes # 0 replace_malloc [d:\drmemory_package\common\alloc_replace.c:2377] # 1 libwinpthread-1.dll!? +0x0 (0x64b4466c <libwinpthread-1.dll+0x466c>) # 2 KERNELBASE.dll!WaitForSingleObjectEx+0xb6 (0x76a12cc7 <KERNELBASE.dll+0x2cc7>) # 3 KERNELBASE.dll!WaitForSingleObjectEx+0xd7 (0x76a12ce8 <KERNELBASE.dll+0x2ce8>) # 4 libwinpthread-1.dll!? +0x0 (0x64b44db3 <libwinpthread-1.dll+0x4db3>) # 5 libwinpthread-1.dll!? +0x0 (0x64b4466c <libwinpthread-1.dll+0x466c>) # 6 libwinpthread-1.dll!? +0x0 (0x64b4cd42 <libwinpthread-1.dll+0xcd42>) # 7 libgcc_s_dw2-1.dll!emutls_alloc [../../../gcc-4.9.2/libgcc/emutls.c:102] # 8 libgcc_s_dw2-1.dll!__emutls_get_address [../../../gcc-4.9.2/libgcc/emutls.c:183] # 9 main [C:\Users\David\Documents\bugs\mingw_leak/bug.c:7] In case the formatting of this email is messed up, you can see all of this information here: https://gist.github.com/DavidEGrayson/97bf529b73315026c8f8 By the way, to get these nice stack traces, I had to compile the MSYS2 gcc package myself using this script: https://github.com/Alexpux/MINGW-packages/blob/c0095d7bd46f293ff0c5c0f2499b17b48bf07e9e/mingw-w64-gcc/PKGBUILD This was an error-prone process that I haven't actually completed yet, but the build got far enough to produce a usable version of libgcc_s_dw2-1.dll with debugging information. Does anyone know what is causing Dr. Memory to report this memory leak? Is it a bug with Dr. Memory, or is there an actual memory leak in mingw-w64? I am trying to go one level deeper, to see if I can reproduce the bug using the __gthread_* functions that emutls.c uses. However, I don't know what header to include or what library to link against in order to use things like __ghtread_active_p() in a standalone C program. Does anyone know how to do that? Alternatively, if someone can recommend a memory leak checker for Windows programs, particularly one that doesn't require recompilation of the target program, I might try it out to see if it reports the same memory leak. Again, this isn't a very high priority problem for me, but it would be nice to get it fixed. Thanks! --David Grayson ------------------------------------------------------------------------------ Don't Limit Your Business. Reach for the Cloud. GigeNET's Cloud Solutions provide you with the tools and support that you need to offload your IT needs and focus on growing your business. Configured For All Businesses. Start Your Cloud Today. https://www.gigenetcloud.com/ _______________________________________________ Mingw-w64-public mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/mingw-w64-public
