Bug #2664
closedscenario template: ndn::Name double free in __cxa_finalize
100%
Description
Steps to reproduce:
- install ndnSIM, and apply #2662 note-1 workaround
- clone ndnSIM-scenario-template
create file
ndnSIM-scenario-template/scenarios/hello.cpp
with following code:#include <ns3/ndnSIM-module.h> int main() { return 0; }
execute
CXXFLAGS='-std=c++0x -Wall' ./waf configure --debug
(#2663 note-1 workaround) followed by./waf --run=hello
Expected: code builds and scenario terminates without error
Actual: code builds, but scenario fails with *** glibc detected *** build/hello: double free or corruption (!prev): 0x00000000014239d0 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6( 0x7de16)[0x7fdaaa543e16]
build/hello(__gnu_cxx::new_allocator<ndn::Block>::deallocate(ndn::Block*, unsigned long) 0x20)[0x4d6654]
build/hello(std::_Vector_base<ndn::Block, std::allocator<ndn::Block> >::_M_deallocate(ndn::Block*, unsigned long) 0x32)[0x4d53c4]
build/hello(std::_Vector_base<ndn::Block, std::allocator<ndn::Block> >::~_Vector_base() 0x56)[0x4d4e12]
build/hello(std::vector<ndn::Block, std::allocator<ndn::Block> >::~vector() 0x42)[0x4d3a54]
build/hello(ndn::Block::~Block() 0x1d)[0x4d06df]
build/hello(ndn::Name::~Name() 0x1d)[0x4d0d7b]
/lib/x86_64-linux-gnu/libc.so.6(__cxa_finalize 0x9d)[0x7fdaaa5019cd]
/usr/local/lib/libns3-dev-ndnSIM-debug.so( 0xb0f436)[0x7fdab0d95436]
Files
Updated by Junxiao Shi over 9 years ago
Workaround:
At end of simulation scenario's main
function, add std::abort()
.
This does not fix the double free problem, but can suppress the error because __cxa_finalize
is not executed if program is aborted.
Updated by Christian Kreuzberger over 9 years ago
I am getting the same error when trying ndn-simple via the scenario template.
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
*** Error in `/home/ckreuz/ndnSIM/my-simulations/build/ndn-simple': double free or corruption (!prev): 0x000000000089ef70 ***
Program received signal SIGABRT, Aborted.
0x00007fffee58acc9 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
56 ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0 0x00007fffee58acc9 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
#1 0x00007fffee58e0d8 in __GI_abort () at abort.c:89
#2 0x00007fffee5c7394 in __libc_message (do_abort=do_abort@entry=1, fmt=fmt@entry=0x7fffee6d5b28 "*** Error in `%s': %s: 0x%s ***\n") at ../sysdeps/posix/libc_fatal.c:175
#3 0x00007fffee5d366e in malloc_printerr (ptr=<optimized out>, str=0x7fffee6d5c10 "double free or corruption (!prev)", action=1) at malloc.c:4996
#4 _int_free (av=<optimized out>, p=<optimized out>, have_lock=0) at malloc.c:3840
#5 0x00007ffff3bd41bf in deallocate (this=<optimized out>, __p=<optimized out>) at /usr/include/c++/4.8/ext/new_allocator.h:110
#6 _M_deallocate (this=<optimized out>, __n=<optimized out>, __p=<optimized out>) at /usr/include/c++/4.8/bits/stl_vector.h:174
#7 ~_Vector_base (this=0x79abd0 <ndn::nfd::CommandOptions::DEFAULT_PREFIX+80>, __in_chrg=<optimized out>) at /usr/include/c++/4.8/bits/stl_vector.h:160
#8 ~vector (this=0x79abd0 <ndn::nfd::CommandOptions::DEFAULT_PREFIX+80>, __in_chrg=<optimized out>) at /usr/include/c++/4.8/bits/stl_vector.h:416
#9 ndn::Block::~Block (this=0x79ab90 <ndn::nfd::CommandOptions::DEFAULT_PREFIX+16>, __in_chrg=<optimized out>) at /usr/local/include/ndn-cxx/encoding/block.hpp:43
#10 0x00007ffff3bd6bad in ndn::Name::~Name (this=0x79ab80 <ndn::nfd::CommandOptions::DEFAULT_PREFIX>, __in_chrg=<optimized out>) at /usr/local/include/ndn-cxx/name.hpp:39
#11 0x00007fffee5905ea in __cxa_finalize (d=0x7ffff4072360) at cxa_finalize.c:56
#12 0x00007ffff3bc5c83 in __do_global_dtors_aux () from /usr/local/lib/libns3-dev-ndnSIM-optimized.so
#13 0x00007fffffffde10 in ?? ()
#14 0x00007ffff7dea73a in _dl_fini () at dl-fini.c:252
Additionally, here is the output from valgrind for build/hello:
http://pastebin.com/y32vBm1j
It looks like there are several invalid free and delete commands, probably related to Name/Block. Though I don't have time to dig into this problem.
Updated by Junxiao Shi over 9 years ago
The Name being double freed is ndn::nfd::CommandOptions::DEFAULT_PREFIX
. I found this out with the following method:
apply
2664-print-Name-dtor.patch
to ndn-cxxrun scenario in gdb; I added
std::cout << "hello" << std::endl;
in the scenario to show where cleanup starts.(gdb) run Starting program: /home/shijunxiao/ndnSIM-scenario-template/build/hello [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". Name::~Name(0x7fffffffe2a0 /) Name::~Name(0x7fffffffdcf0 /) Name::~Name(0x7fffffffdee0 /) hello Name::~Name(0xabbe60 /723821fd-f534-44b3-80d9-44bf5f58bbbb) Name::~Name(0xabbb40 /localhost/nfd) hello: ../src/name.cpp:87: ndn::Name::~Name(): Assertion `it != getAllNameSet().end()' failed. Program received signal SIGABRT, Aborted. 0x00007fffeb4ba0d5 in __GI_raise (sig=<optimized out>) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64 64 ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory. (gdb) bt #0 0x00007fffeb4ba0d5 in __GI_raise (sig=<optimized out>) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64 #1 0x00007fffeb4bd83b in __GI_abort () at abort.c:91 #2 0x00007fffeb4b2d9e in __assert_fail_base (fmt=<optimized out>, assertion=0x7d6950 "it != getAllNameSet().end()", file=0x7d6940 "../src/name.cpp", line=<optimized out>, function=<optimized out>) at assert.c:94 #3 0x00007fffeb4b2e42 in __GI___assert_fail (assertion=0x7d6950 "it != getAllNameSet().end()", file=0x7d6940 "../src/name.cpp", line=87, function=0x7d6b10 "ndn::Name::~Name()") at assert.c:103 #4 0x00000000006c7862 in ndn::Name::~Name (this=0xabbb40, __in_chrg=<optimized out>) at ../src/name.cpp:87 #5 0x00007fffeb4bf9cd in __cxa_finalize (d=0x7ffff27df7e0) at cxa_finalize.c:56 #6 0x00007ffff1f21976 in __do_global_dtors_aux () from /home/shijunxiao/local/lib/libns3-dev-ndnSIM-debug.so
Stack frame 4 shows the Name being destructed is 0xabbb40, which has been destructed earlier and its value was
/localhost/nfd
.
The low address also indicates that it's a static constant.There are only two Name constants of this value in the code:
ndn-cxx/src/management/nfd-command-options.cpp
andndnSIM/model/ndn-l3-protocol.cpp
.
Changing the value ofndn::nfd::CommandOptions::DEFAULT_PREFIX
to something else, and gdb shows the Name changed, so that I can concludendn::nfd::CommandOptions::DEFAULT_PREFIX
is the Name being double freed.
This Bug is caused by linking ndn-cxx static library twice: once in libns3-dev-ndnSIM-debug.so
and again in the scenario binary.
After those analysis, I have found the solution. Please add me as a Developer of ndnSIM Redmine site, and assign this issue to me. I'll submit the solution afterwards.
Updated by Christian Kreuzberger over 9 years ago
As yous aid, the problem is caused by ndn-cxx STATIC library being linked twice. The fix is not to "fix" ndn::Data (though obviously this could be another problem), but to fix the build scripts.
The changes are simple:
i) (this is preliminary and just fixes some warnings in g++/gcc):
remove -pedantic from .waf-tools/default-compiler-flags.py
ii) add a waf-conf "check" to wscript, that checks that boost is at least at version 1.53 and in addition that boost lib system and iostreams are available
iii) fix waf-build by changing the deps from NDN_CXX
+ ... to BOOST
BOOST_IOSTREAMS
+ ...
I've done that, and the patch is attached.
Updated by Junxiao Shi over 9 years ago
My solution is much simpler than this. I'm waiting for this Bug to be assigned to me before uploading the solution.
Updated by Junxiao Shi over 9 years ago
- Tracker changed from Task to Bug
- Category set to build
- Status changed from New to In Progress
- Assignee set to Junxiao Shi
- Estimated time set to 0.50 h
Updated by Junxiao Shi over 9 years ago
- Status changed from In Progress to Code review
- % Done changed from 0 to 100
Updated by Junxiao Shi over 9 years ago
The PullRequest was rejected with the following reason:
This is not right. The library needs to be linked, as in some cases it is needed to use ndn-cxx directly from the extensions or scenarios.
I disagree with this reason.
Not linking ndn-cxx in scenario does not prevent the scenario to use ndn-cxx directly.
- The compiler can find ndn-cxx headers because
pkg-config --cflags libndn-cxx
output is appended. - The linker can find ndn-cxx symbols because they appear in libns3*-ndnSIM-*.so.
The correct way is to use ndn-cxx as a shared library (though this option is not yet available for cxx...).
Yes, but we don't have to wait for that, given there's a simple solution.
Updated by Junxiao Shi over 9 years ago
- Related to Bug #2842: "double free" reported when smart pointer is created outside of the wrapper class added
Updated by Junxiao Shi over 9 years ago
- Status changed from Code review to Closed
The bug no longer exists when ndn-cxx is installed as a shared library.