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 almost 10 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 almost 10 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 almost 10 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 almost 10 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 almost 10 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 almost 10 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 almost 10 years ago
- Status changed from In Progress to Code review
- % Done changed from 0 to 100
Updated by Junxiao Shi almost 10 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 almost 10 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.