I am about to write a (very) large code for a scientific project, where a large numbers of allocatable arrays will be used. Is there an intrinsic fortran function or maybe a compiler flag which I can used which checks that all allocatable variables have been correctly deallocated? I am using gfortran.
gcc and therefore also gfortran can use the AddressSanitizer library to detect memory leaks. This can be enabled using the -fsanitize=address option.
The output will then be similar to what valgrind produces:
==26339==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 144 byte(s) in 1 object(s) allocated from:
#0 0x7f46fad68510 in malloc (/usr/lib64/libasan.so.4+0xdc510)
#1 0x407754 in __sectiontest_MOD_constructor /users/tiziano/work/tests/fortran/cp2k_input_parser/recursive_mwe_alternative/recursive_mwe.f90:27
#2 0x403939 in __sectiontest_MOD_demo /users/tiziano/work/tests/fortran/cp2k_input_parser/recursive_mwe_alternative/recursive_mwe.f90:95
#3 0x408564 in MAIN__ /users/tiziano/work/tests/fortran/cp2k_input_parser/recursive_mwe_alternative/recursive_mwe_prog.f90:5
#4 0x4085a4 in main /users/tiziano/work/tests/fortran/cp2k_input_parser/recursive_mwe_alternative/recursive_mwe_prog.f90:2
#5 0x7f46f9d8ef89 in __libc_start_main (/lib64/libc.so.6+0x20f89)
Direct leak of 96 byte(s) in 1 object(s) allocated from:
#0 0x7f46fad68510 in malloc (/usr/lib64/libasan.so.4+0xdc510)
#1 0x407754 in __sectiontest_MOD_constructor /users/tiziano/work/tests/fortran/cp2k_input_parser/recursive_mwe_alternative/recursive_mwe.f90:27
#2 0x403d72 in __sectiontest_MOD_demo /users/tiziano/work/tests/fortran/cp2k_input_parser/recursive_mwe_alternative/recursive_mwe.f90:95
#3 0x408564 in MAIN__ /users/tiziano/work/tests/fortran/cp2k_input_parser/recursive_mwe_alternative/recursive_mwe_prog.f90:5
#4 0x4085a4 in main /users/tiziano/work/tests/fortran/cp2k_input_parser/recursive_mwe_alternative/recursive_mwe_prog.f90:2
#5 0x7f46f9d8ef89 in __libc_start_main (/lib64/libc.so.6+0x20f89)
Indirect leak of 144 byte(s) in 1 object(s) allocated from:
#0 0x7f46fad68510 in malloc (/usr/lib64/libasan.so.4+0xdc510)
#1 0x405fec in __sectiontest_MOD_section_assign /users/tiziano/work/tests/fortran/cp2k_input_parser/recursive_mwe_alternative/recursive_mwe.f90:50
#2 0x408237 in __sectiontest_MOD_constructor /users/tiziano/work/tests/fortran/cp2k_input_parser/recursive_mwe_alternative/recursive_mwe.f90:30
#3 0x403d72 in __sectiontest_MOD_demo /users/tiziano/work/tests/fortran/cp2k_input_parser/recursive_mwe_alternative/recursive_mwe.f90:95
#4 0x408564 in MAIN__ /users/tiziano/work/tests/fortran/cp2k_input_parser/recursive_mwe_alternative/recursive_mwe_prog.f90:5
#5 0x4085a4 in main /users/tiziano/work/tests/fortran/cp2k_input_parser/recursive_mwe_alternative/recursive_mwe_prog.f90:2
#6 0x7f46f9d8ef89 in __libc_start_main (/lib64/libc.so.6+0x20f89)
SUMMARY: AddressSanitizer: 384 byte(s) leaked in 3 allocation(s).
As stated before in the comments, memory leaks should not be occurring with allocatables. On the other hand has experience shown that there can be compiler bugs which can cause memory leaks nevertheless.
Related
I'm using ASAN address sanitizer to detect memory issues. When the program stops ASAN complains about the following:
==102121==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 537 byte(s) in 1 object(s) allocated from:
#0 0x75cb48 in operator new(unsigned long) (/home/app+0x75cb48)
#1 0x7dca83 in __gnu_cxx::new_allocator<char>::allocate(unsigned long, void const*) /opt/rh/devtoolset-7/root/usr/include/c++/7/ext/new_allocator.h:111
#2 0x7ce766 in std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) /opt/rh/devtoolset-7/root/usr/include/c++/7/bits/basic_string.tcc:1057
#3 0x7cc54d in std::string::_Rep::_M_clone(std::allocator<char> const&, unsigned long) (/home/app+0x7cc54d)
#4 0x7c1f2a in std::string::reserve(unsigned long) /opt/rh/devtoolset-7/root/usr/include/c++/7/bits/basic_string.tcc:960
#5 0x7fa0a639c6f5 in std::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> >::overflow(int) (/lib64/libstdc++.so.6+0x9b6f5)
Direct leak of 24 byte(s) in 1 object(s) allocated from:
#0 0x75cec8 in operator new(unsigned long, std::nothrow_t const&) (/home/app+0x75cec8)
#1 0x7fa0a635df1d in __cxa_thread_atexit (/lib64/libstdc++.so.6+0x5cf1d)
Indirect leak of 24 byte(s) in 1 object(s) allocated from:
#0 0x75cec8 in operator new(unsigned long, std::nothrow_t const&) (/home/app+0x75cec8)
#1 0x7fa0a635df1d in __cxa_thread_atexit (/lib64/libstdc++.so.6+0x5cf1d)
I've seen on the ASAN page that it can come from the fact the the standard library is statically linked. Although, in my case it is dynamic one.
The application is compiled with devtoolset-7 on RHEL.
Do you have any idea where the leak comes from?
You can get more info than
#0 0x75cb48 in operator new(unsigned long) (/home/app+0x75cb48)
by using llvm-symbolizer.
Download it, and set the environment variable
ASAN_SYMBOLIZER_PATH=/usr/where/ever/the/binary/is
If you are sure that the leak is a false alarm, you can use a suppression file:
create a suppression text file and add to it: leak: __cxa_thread_atexit
Set environment variable
LSAN_OPTIONS=suppressions=path/to/suppr.txt
and then run your app.
http://clang.llvm.org/docs/AddressSanitizer.html#symbolizing-the-reports
I am having a problem debugging my code and am a bit confused by the gdb output. I have attached the gdb output below. The last 2 lines, line #13 and #14 are my code, but everything else is from the C++ library. What is confusing to me is that from about line #7 upward, it appears to be calling delete. This is initialization code and there are no deletes nor frees being called in the code flow. But something is causing delete to be called somewhere in the C++ library.
this is on a debian box with g++ 4.7.2
Anybody have a clue that could help me along?
EDIT: thanks you guys for your help. I indeed think there is something else going on here. Since the intent of my code is to construct a string using several append() calls, I added a call to reserve() in the ctor for that string so it would be large enough to handle a few append() calls without having to get more space. This has apparently helped because it is now harder for me to force the crash. But I do agree that the cause is probably elsewhere in my code. Again, thanks for all your help.
Program received signal SIGABRT, Aborted.
0xb7fe1424 in __kernel_vsyscall ()
(gdb) bt
#0 0xb7fe1424 in __kernel_vsyscall ()
#1 0xb7a9a941 in *__GI_raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
#2 0xb7a9dd72 in *__GI_abort () at abort.c:92
#3 0xb7ad6e15 in __libc_message (do_abort=2, fmt=0xb7baee70 "*** glibc detected *** %s: %s: 0x%s ***\n") at ../sysdeps/unix/sysv/linux/libc_fatal.c:189
#4 0xb7ae0f01 in malloc_printerr (action=<optimized out>, str=0x6 <Address 0x6 out of bounds>, ptr=0xb71117f0) at malloc.c:6283
#5 0xb7ae2768 in _int_free (av=<optimized out>, p=<optimized out>) at malloc.c:4795
#6 0xb7ae581d in *__GI___libc_free (mem=0xb71117f0) at malloc.c:3738
#7 0xb7f244bf in operator delete(void*) () from /usr/lib/i386-linux-gnu/libstdc++.so.6
#8 0xb7f8b48b in std::string::_Rep::_M_destroy(std::allocator<char> const&) () from /usr/lib/i386-linux-gnu/libstdc++.so.6
#9 0xb7f8b4d0 in ?? () from /usr/lib/i386-linux-gnu/libstdc++.so.6
#10 0xb7f8c7a0 in std::string::reserve(unsigned int) () from /usr/lib/i386-linux-gnu/libstdc++.so.6
#11 0xb7f8caaa in std::string::append(char const*, unsigned int) () from /usr/lib/i386-linux-gnu/libstdc++.so.6
#12 0xb7f8cb76 in std::string::append(char const*) () from /usr/lib/i386-linux-gnu/libstdc++.so.6
#13 0x0804fa38 in MethodRequest::MethodRequest (this=0x80977a0) at cLogProxy.cpp:26
#14 0x0804fac0 in DebugMethodRequest::DebugMethodRequest (this=0x80977a0,
thanks,
-Andres
You are calling std::string::append, that ultimately results in delete getting called. If we go through the steps involved in std::string::append, it might make more sense why delete gets called.
Say you have:
std::string s("abc");
s.append("def");
When you create s, memory has to be allocated to hold "abc". At the end of s.append("def");, there has to be enough memory associated with s to hold "abcdef". Steps to get there:
Get the length of s => 3.
Get the length of the input string "def" => 3.
Add them to figure out the length of the new string. => 6.
Allocate memory to hold the new string.
Copy "abc" to the newly allocated memory.
Append "def" to the newly allocated memory.
Associate the newly allocated memory with s.
Delete the old memory associated with s. (This is where delete comes into picture).
Something is doing string computations that are resulting in deletes internally. Seems likely something else is trashing memory.
Currently we are seeing our processes taking too long with mmap call.
Once the process reaches to roughly ~2.8 GB, the mmap call takes upto 100
seconds and its being killed by heart beat mechanism built in the process.
Would like to know anyone has seen this issue or know why would mmap take
more than 100 seconds when asked for memory. In all the cases the stack trace
looks the same but memory is allocated in different parts of the code.
Host and compiler info:
Host memory: 70 gb OS: redhat 6.3 compiler: gcc 4.4.6 process memory
limit(32 bit): 4 gb No Swap configured
And when this happens the host still has 50GB of memory left.
Stack Trace:
#0 0x55575430 in __kernel_vsyscall ()
#1 0x560f9dd8 in mmap () from /lib/libc.so.6
#2 0x5608f2db in _int_malloc () from /lib/libc.so.6
#3 0x5608fb7e in malloc () from /lib/libc.so.6
#4 0x55fb509a in operator new(unsigned int) () from /usr/lib/libstdc++.so.6
#5 0x55f91ed6 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::_Rep::_S_create(unsigned int, unsigned int, std::allocator<char> const&) ()
from /usr/lib/libstdc++.so.6
I have some issues with the new operator in libstdc++. I wrote a program in C++ and had some problems with the memory management.
After having debugged with gdb to determine what is eating up my ram I got the following for info proc mappings
Mapped address spaces:
Start Addr End Addr Size Offset objfile
0x400000 0x404000 0x4000 0 /home/sebastian/Developement/powerserverplus-svn/psp-job-distributor/Release/psp-job-distributor
0x604000 0x605000 0x1000 0x4000 /home/sebastian/Developement/powerserverplus-svn/psp-job-distributor/Release/psp-job-distributor
0x605000 0x626000 0x21000 0 [heap]
0x7ffff0000000 0x7ffff0021000 0x21000 0
0x7ffff0021000 0x7ffff4000000 0x3fdf000 0
0x7ffff6c7f000 0x7ffff6c80000 0x1000 0
0x7ffff6c80000 0x7ffff6c83000 0x3000 0
0x7ffff6c83000 0x7ffff6c84000 0x1000 0
0x7ffff6c84000 0x7ffff6c87000 0x3000 0
0x7ffff6c87000 0x7ffff6c88000 0x1000 0
0x7ffff6c88000 0x7ffff6c8b000 0x3000 0
0x7ffff6c8b000 0x7ffff6c8c000 0x1000 0
0x7ffff6c8c000 0x7ffff6c8f000 0x3000 0
0x7ffff6c8f000 0x7ffff6e0f000 0x180000 0 /lib/x86_64-linux-gnu/libc-2.13.so
0x7ffff6e0f000 0x7ffff700f000 0x200000 0x180000 /lib/x86_64-linux-gnu/libc-2.13.so
0x7ffff700f000 0x7ffff7013000 0x4000 0x180000 /lib/x86_64-linux-gnu/libc-2.13.so
0x7ffff7013000 0x7ffff7014000 0x1000 0x184000 /lib/x86_64-linux-gnu/libc-2.13.so
That's just snipped out of it. However, everything is normal. Some of this belongs to the code for the standard libs, some if it is heap and some of it are stack sections for threads I created.
But. there is this one section I id not figure out why it is allocated:
0x7ffff0000000 0x7ffff0021000 0x21000 0
0x7ffff0021000 0x7ffff4000000 0x3fdf000 0
These two sections are created at a seemlike random time. There is several hours of debugging no similarity in time nor at a certain created thread or so. I set a hardware watch point with awatch *0x7ffff0000000 and gave it several runs again.
These two sections are created at nearly the same time within the same code section of a non-debuggable function (gdb shows it in stack as in ?? () from /lib/x86_64-linux-gnu/libc.so.6). More exact this is a sample stack where it occured:
#0 0x00007ffff6d091d5 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#1 0x00007ffff6d0b2bd in calloc () from /lib/x86_64-linux-gnu/libc.so.6
#2 0x00007ffff7dee28f in _dl_allocate_tls () from /lib64/ld-linux-x86-64.so.2
#3 0x00007ffff77c0484 in pthread_create##GLIBC_2.2.5 () from /lib/x86_64-linux-gnu/libpthread.so.0
#4 0x00007ffff79d670e in Thread::start (this=0x6077c0) at ../src/Thread.cpp:42
#5 0x000000000040193d in MultiThreadedServer<JobDistributionServer_Thread>::Main (this=0x7fffffffe170) at /home/sebastian/Developement/powerserverplus-svn/mtserversock/src/MultiThreadedServer.hpp:55
#6 0x0000000000401601 in main (argc=1, argv=0x7fffffffe298) at ../src/main.cpp:29
Another example would be here (from a differet run):
#0 0x00007ffff6d091d5 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#1 0x00007ffff6d0bc2d in malloc () from /lib/x86_64-linux-gnu/libc.so.6
#2 0x00007ffff751607d in operator new(unsigned long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3 0x000000000040191b in MultiThreadedServer<JobDistributionServer_Thread>::Main (this=0x7fffffffe170) at /home/sebastian/Developement/powerserverplus-svn/mtserversock/src/MultiThreadedServer.hpp:53
#4 0x0000000000401601 in main (argc=1, argv=0x7fffffffe298) at ../src/main.cpp:29
The whole thing says that it occurs at the calloc called from the pthread lib or in another situation it was the new operator or the malloc called from it. It doesn't matter which new it is - in several runs it occured at nearly every new or thread creation in my code. The only "constant" thing with it is that it occurs every time in the libc.so.6.
No matter at which point of the code,
no matter if used with malloc or calloc,
no matter after how much time the program ran,
no matter after how many threads have been created,
it is always that section: 0x7ffff0000000 - 0x7ffff4000000.
Everytime the program runs. But everytime at another point in the program. I am really confused because it allocated 67MB of virtual space but it does not use it.
When watching the variables it created there, especially watched those which are created when malloc or calloc were called by libc, none of this space is used by them. They are created in a heap section which is far away from that address range (0x7ffff0000000 - 0x7ffff4000000).
Edit:
I checked the stack size of the parent process too and got a usage of 8388608 Bytes, which is 0x800000 (~8MB). To get these values I did:
pthread_attr_t attr;
size_t stacksize;
struct rlimit rlim;
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &stacksize);
getrlimit(RLIMIT_STACK, &rlim);
fit into a size_t variable. */
printf("Resource limit: %zd\n", (size_t) rlim.rlim_cur);
printf("Stacksize: %zd\n", stacksize);
pthread_attr_destroy(&attr);
Please help me with that. I am really confused about that.
It looks like it is allocating a stack space for a thread.
The space will be used as you make function calls in the thread.
But really what is is doing is none of your business. It is part of the internal implementation of pthread_create() it can do anything it likes in there.
First I am populating a structure which is quite big and have interrelations. and then I serialize that to a binary archive. Size of that structure depends on what data I feed to the program. I see the program taking ~2GB memory to build the structure which is expected and acceptable.
Then I start serializing the object. and I see program eating RAM while serializing. RAM usage growing till it reaches near 100%. swap usage is still 0 bytes.
and then the Application crashes. with a exception of bad_alloc on new
Why would serialization process take so much RAM and time ? and why would it crash while allocating memory when swap is empty ? the backtrace is too long to be pasted in full.
#0 0xb7fe1424 in __kernel_vsyscall ()
#1 0xb7c6e941 in raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
#2 0xb7c71e42 in abort () at abort.c:92
#3 0xb7e92055 in __gnu_cxx::__verbose_terminate_handler() () from /usr/lib/libstdc++.so.6
#4 0xb7e8ff35 in ?? () from /usr/lib/libstdc++.so.6
#5 0xb7e8ff72 in std::terminate() () from /usr/lib/libstdc++.so.6
#6 0xb7e900e1 in __cxa_throw () from /usr/lib/libstdc++.so.6
#7 0xb7e90677 in operator new(unsigned int) () from /usr/lib/libstdc++.so.6
#8 0xb7f00a9f in boost::archive::detail::basic_oarchive_impl::save_pointer(boost::archive::detail::basic_oarchive&, void const*, boost::archive::detail::basic_pointer_oserializer const*) () from /usr/lib/libboost_serialization.so.1.42.0
#9 0xb7effb42 in boost::archive::detail::basic_oarchive::save_pointer(void const*, boost::archive::detail::basic_pointer_oserializer const*) () from /usr/lib/libboost_serialization.so.1.42.0
#10 0x082d052c in void boost::archive::detail::save_pointer_type<boost::archive::binary_oarchive>::non_polymorphic::save<gcl::NestedConnection<gcl::Section, gcl::NestedConnection<gcl::Paragraph, gcl::NestedConnection<gcl::Line, void> > > >(boost::archive::binary_oarchive&, gcl::NestedConnection<gcl::Section, gcl::NestedConnection<gcl::Paragraph, gcl::NestedConnection<gcl::Line, void> > >&) ()
#11 0x082d0472 in void boost::archive::detail::save_pointer_type<boost::archive::binary_oarchive>::save<gcl::NestedConnection<gcl::Section, gcl::NestedConnection<gcl::Paragraph, gcl::NestedConnection<gcl::Line, void> > > >(boost::archive::binary_oarchive&, gcl::NestedConnection<gcl::Section, gcl::NestedConnection<gcl::Paragraph, gcl::NestedConnection<gcl::Line, void> > > const&) ()
.......
#172 0x082a91d8 in boost::archive::detail::interface_oarchive<boost::archive::binary_oarchive>::operator<< <gcl::Collation const> (this=0xbfffe500, t=...) at /usr/include/boost/archive/detail/interface_oarchive.hpp:64
#173 0x082a6298 in boost::archive::detail::interface_oarchive<boost::archive::binary_oarchive>::operator&<gcl::Collation> (this=0xbfffe500, t=...) at /usr/include/boost/archive/detail/interface_oarchive.hpp:72
#174 0x0829bd63 in main (argc=4, argv=0xbffff3f4) at /home/neel/projects/app/main.cpp:93
Program works properly When a smaller data is feeded to it.
Using Linux 64bit with 32bit PAE kernel boost 1.42
program was working without a crash few revision ago. I recently added some more bytes to the structures. may be then it was not reaching the end of RAM and now its reaching.
But why would new crash when there is enough swap ? why would serialization process take so much RAM ?
Question: why would it crash while allocating memory when swap is empty ?
The allocated object is too big to fit anywhere in the virtual address space:
The allocated object is humongous
virtual address space is too fragmented
virtual address space is all allocated
If your application is complied as a 32bits, the process virtual address space is limited to 4Gb.
Question: why would serialization process take so much RAM ?
I have not found any evidence why.
I realized that serialization process was taking extra memory, for its own house keeping works. and that was hitting the 3GB Barrier To stop serialization process from taking extra memory I disabled object tracking BOOST_CLASS_TRACKING and that fixed extra memory overhead.