GDB not giving details at segfault cygwin - c++

So I am trying to debug a segfault in a C++ project for school. The project uses a makefile to compile. When I run the program under gdb (using cygwin) I get the segfault but when I try to use the "l" command to show the code I get different code than expected, and when I use "frame", gdb only prints the name of the function instead of the code that last executed.
Program received signal SIGSEGV, Segmentation fault.
0x000000010041570b in NodeCorrectness::eval(Alignment const&) ()
(gdb) l
1 /* advapi32.cc: Win32 replacement functions.
2
3 This file is part of Cygwin.
4
5 This software is a copyrighted work licensed under the terms of the
6 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
7 details. */
8
9 #include "winsup.h"
10 #include <winioctl.h>
(gdb) frame
#0 0x000000010041570b in NodeCorrectness::eval(Alignment const&) ()
(gdb)
Using backtrace I get the following:
(gdb) bt
#0 0x000000000042781b in NodeCorrectness::eval(Alignment const&) ()
#1 0x0000000000421a2f in MeasureCombination::printMeasures(Alignment const&, std::ostream&) const ()
#2 0x00000000004fbedf in makeReport(Graph const&, Graph&, Alignment const&, MeasureCombination const&, Method*, std::basic_ofstream<char, std::char_traits<char> >&)
()
#3 0x00000000004fe6cd in saveReport(Graph const&, Graph&, Alignment const&, MeasureCombination const&, Method*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) ()
#4 0x00000000004d06a7 in NormalMode::run(ArgumentParser&) ()
#5 0x000000000040a655 in main ()
(gdb)
So gdb does not let me see where exactly the segfault occurred. Any reason for this?

Related

gdb backtrace - show inlined functions, like `addr2line -i` does

I have gdb attached to process. I print backtrace, one of frames looks like this:
#9 0x000055b748d7467b in CA::CryptUserKeysCache::addSongKeyFast (this=0x55b74e141a90, group_color=..., timePeriodValidUnit=timePeriodValidUnit#entry=366, keyIsValidFromTime=1573653252507218,
useSystemValues=useSystemValues#entry=false) at /usr/include/c++/8/bits/shared_ptr_base.h:1307
That is my function, but definitely not my file. I expect this is due to inlining. Is there a command that will show me how this inlining proceeded? Something akin to addr2line -i?
For comparison, addr2line with slightly different backtrace, but close.
addr2line plain:
CA::CCryptSongPrivateGroupMgrKey::JoinMyselfToGroup(Borg::AbstractGroupHash const&) at /usr/local/linux64-hard-2.17/include/boost/multiprecision/cpp_int.hpp:987
CA::CryptUserKeysCache::addSongKeyFast(Borg::AbstractGroupHash const&, unsigned short, long, bool) at /home2/mateuszl/git/borg-engine/core_inter_headers/core_separate_libs/libs/crypto_types/src/CryptUserKeysCache.cpp:1699
with -i:
CA::CCryptSongPrivateGroupMgrKey::JoinMyselfToGroup(Borg::AbstractGroupHash const&) at /usr/local/linux64-hard-2.17/include/boost/multiprecision/cpp_int.hpp:987
(inlined by) ?? at /usr/local/linux64-hard-2.17/include/boost/multiprecision/cpp_int.hpp:1073
(inlined by) ?? at /usr/local/linux64-hard-2.17/include/boost/multiprecision/number.hpp:45
(inlined by) ?? at /home2/mateuszl/git/borg-engine/core_inter_headers/core_separate_libs/libs/uint128/src/../include/borg/uint128/uint128.h:50
(inlined by) CA::CCryptSongPrivateGroupMgrKey::JoinMyselfToGroup(Borg::AbstractGroupHash const&) at /home2/mateuszl/git/borg-engine/core_inter_headers/core_separate_libs/libs/crypto_song/src/CCryptSongPrivateGroupMgrKey.cpp:234
CA::CryptUserKeysCache::addSongKeyFast(Borg::AbstractGroupHash const&, unsigned short, long, bool) at /home2/mateuszl/git/borg-engine/core_inter_headers/core_separate_libs/libs/crypto_types/src/CryptUserKeysCache.cpp:1699

Why segmentation fault happened when i define a const string in a google test programe?

I want to run unit test with google test, but got Segmentation fault. I have just define a global const string, and RUN_ALL_TESTS, why?
the gdb result is :
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[==========] Running 0 tests from 0 test cases.
[==========] 0 tests from 0 test cases ran. (1 ms total)
[ PASSED ] 0 tests.
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff6fe415c in __GI___libc_free (mem=0x603588) at malloc.c:2947
2947 malloc.c: No such file or directory.
And flowing is the backtrace:
(gdb) bt
#0 0x00007ffff6fe415c in __GI___libc_free (mem=0x603588) at malloc.c:2947
#1 0x00007ffff75fa36f in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#2 0x00007ffff7bb25ba in void std::_Destroy<std::string>(std::string*) () from /home/caros/src/secsdk/datasecurity-upgrade/external/libgtest.so
#3 0x00007ffff7bb04bd in void std::_Destroy_aux<false>::__destroy<std::string*>(std::string*, std::string*) () from /home/caros/src/secsdk/datasecurity-upgrade/external/libgtest.so
#4 0x00007ffff7bac65c in void std::_Destroy<std::string*>(std::string*, std::string*) () from /home/caros/src/secsdk/datasecurity-upgrade/external/libgtest.so
#5 0x00007ffff7ba68f3 in void std::_Destroy<std::string*, std::string>(std::string*, std::string*, std::allocator<std::string>&) () from /home/caros/src/secsdk/datasecurity-upgrade/external/libgtest.so
#6 0x00007ffff7ba08b2 in std::vector<std::string, std::allocator<std::string> >::~vector() () from /home/caros/src/secsdk/datasecurity-upgrade/external/libgtest.so
#7 0x00007ffff6f9d53a in __cxa_finalize (d=0x7ffff7b2b440) at cxa_finalize.c:56
#8 0x00007ffff78b7ea3 in __do_global_dtors_aux () from /home/caros/src/secsdk/datasecurity-upgrade/external/libgmock.so
#9 0x00007fffffffd5e0 in ?? ()
#10 0x00007ffff7dea7da in _dl_fini () at dl-fini.c:252
Backtrace stopped: frame did not save the PC
This is my whole source code:
#include <iostream>
#include "gtest/gtest.h"
#include "gmock/gmock.h"
const std::string fsdfsdf = "sdfsdfsd";
int main(int argc, char* argv[]) {
testing::InitGoogleMock(&argc, argv);
RUN_ALL_TESTS();
return 0;
}
I expect the programe finished without segmentation fault.
why?
There doesn't appear to be anything wrong with your code. The problem is likely in the environment.
You didn't say where libgtest.so and libgmock.so came from. Perhaps they are incompatible with your version of g++. Hard to tell.
Running your program under Valgrind may provide additional clues.

How can I debug Boost by viewing the file after precompilation?

I'm getting a very weird bug when defining a test suite with boost like this:
BOOST_AUTO_TEST_SUITE(zerocoin_implementation_tests)
The error looks like this:
terminate called after throwing an instance of 'std::length_error'
what(): basic_string::_M_create
Here's the relevant backtrace:
#5 0x00007ffff5ce6fe8 in __cxa_throw () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6 0x00007ffff5ce2875 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#7 0x00007ffff5d7c949 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_create(unsigned long&, unsigned long) ()
from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#8 0x00007ffff70afe15 in boost::unit_test::test_unit::test_unit(boost::unit_test::basic_cstring<char const>, boost::unit_test::basic_cstring<char const>, unsigned long, boost::unit_test::test_unit_type) () from /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.so.1.65.1
#9 0x00007ffff70b0456 in boost::unit_test::test_suite::test_suite(boost::unit_test::basic_cstring<char const>, boost::unit_test::basic_cstring<char const>, unsigned long) () from /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.so.1.65.1
#10 0x00007ffff70b0612 in boost::unit_test::ut_detail::auto_test_unit_registrar::auto_test_unit_registrar(boost::unit_test::basic_cstring<char const>, boost::unit_test::basic_cstring<char const>, unsigned long, boost::unit_test::decorator::collector&) ()
from /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.so.1.65.1
From what I can tell, this has to do with Boost trying to create a max length string. I'd like to see exactly what it is doing. What's the best way of expanding boost macros to see the pre-compiled version?
Side Note
Weirdly, if I change the line very slightly to:
BOOST_AUTO_TEST_SUITE(zerocsoin_implementation_tests)
I get the following error:
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
And backtrace:
#6 0x00007ffff5ce7594 in operator new(unsigned long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#7 0x00007ffff70afe15 in boost::unit_test::test_unit::test_unit(boost::unit_test::basic_cstring<char const>, boost::unit_test::basic_cstring<char const>, unsigned long, boost::unit_test::test_unit_type) () from /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.so.1.65.1
#8 0x00007ffff70b0456 in boost::unit_test::test_suite::test_suite(boost::unit_test::basic_cstring<char const>, boost::unit_test::basic_cstring<char const>, unsigned long) () from /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.so.1.65.1
#9 0x00007ffff70b0612 in boost::unit_test::ut_detail::auto_test_unit_registrar::auto_test_unit_registrar(boost::unit_test::basic_cstring<char const>, boost::unit_test::basic_cstring<char const>, unsigned long, boost::unit_test::decorator::collector&) ()
from /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.so.1.65.1
The source code for the file (and the rest of the project) can be found here: https://github.com/phoreproject/Phore/blob/segwit/src/test/zerocoin_implementation_tests.cpp
Diff that probably caused the bug: https://github.com/phoreproject/phore/compare/master...segwit#diff-bb4f094cc636d668944ed6af9b72c0d9
Two approaches:
Exception Breakpoints
Just start the test in the debugger and catch the exception.
In gdb you could do
(gdb) catch throw
Catchpoint 2 (throw)
which act like a general breakpoint. Visual Studio has a Manage Exeptions dialog.¹
Boost Test Breakpoints
For debugging Boost Test I like to set a break at the test_method member of the specific test case class I want to break at. E.g. with a test_runner that has a few nested suites like:
./test_runner --list_content
import*
utility*
xml*
xml_utilities*
child_text_test*
loggable_xml_path_test*
And we run these 3 tests like:
./test_runner -t import/utility/xml
Running 3 test cases...
*** No errors detected
To debug them with gdb I'd do
gdb ./test_runner
start -t import/utility/xml
Which stops at main, then I type:
break import::utility::xml
Auto completion helps, so to get the exact names, you can just pick from the completions:
xml
xml::as_element(xmlpp::Node const&)
xml::attr_value(xmlpp::Element const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
xml::attr_value(xmlpp::Node const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
xml::child_text[abi:cxx11](xmlpp::Element const&, char const*)
xml::child_text_test
xml::child_text_test::test_method()
xml::child_text_test_invoker()
xml::child_text_test_registrar62
xml::end_suite94_registrar94
xml::first_child(xmlpp::Element const&, char const*)
xml::get_content[abi:cxx11](xmlpp::Element const&)
xml::get_content[abi:cxx11](xmlpp::Node const*)
xml::is_attr_value(xmlpp::Node const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
xml::loggable_xml_path[abi:cxx11](xmlpp::Node const&)
xml::loggable_xml_path_test
xml::loggable_xml_path_test::test_method()
xml::loggable_xml_path_test_invoker()
xml::loggable_xml_path_test_registrar77
xml::trace_xml(xmlpp::Element const&, LogSource::LogTx)
xml::trace_xml_formatted(xmlpp::Element const&, LogSource::LogTx)
xml::xml_registrar20
xml::xml_utilities
xml::xml_utilities::test_method()
xml::xml_utilities_invoker()
xml::xml_utilities_registrar22
Pick the ones named test_method(), e.g.
break import::utility::xml::child_text_test::test_method()
Breakpoint 2 at 0x730762: file /path/src/import/utility/xml_tests.cpp, line 62.
Now you can continue execution and the debugger will automatic pause execution at the start of your unit test.
¹ see also
Make Visual Studio break on User (std::exception) Exceptions?
How do I make VC++'s debugger break on exceptions?

Why does a call to write(3) terminate the thread?

I have a thread that saves to a file. This works fine probably more than 99.9% of the time. Sometimes, though, the thread terminates unexpectedly in the same place every time, a call to write() (the BSD system call). The actual call to write() is very simple:
ssize_t wr = ::write(m_fd, buffer, (size_t)bytes);
At the time of the exit, the buffer is 4 bytes of zeros, bytes is 4, and the file descriptor is the same as all the previous writes made in this thread. I installed a clean-up function using pthread_cleanup_push() that is called from pthread_exit() so I can poke around in the debugger when this unexpected exit occurs.
The question is, why does write() do this at all instead of returning an error? Can I stop it from exiting and handle an error without causing the thread to terminate? The process continues seemingly unaffected, and there are a dozen other threads that seem to continue to function normally after this unexpected exit occurs. This is OS X 10.11.6.
I notice a call to tramp_cerror() that does not seem to be documented anywhere, in fact if you Google it nothing comes up anywhere at all. Am I the first person in the world to wonder what it does and why it seems empowered to terminate my thread?
This is the stack:
#0 0x01c1e388 in cleanup(void*) at ThreadAny.cpp:32
#1 0x0728900b in _pthread_exit ()
#2 0x07289adc in pthread_exit ()
#3 0x07286bc2 in _pthread_exit_if_canceled ()
#4 0x9189ed9d in cerror ()
#5 0x918a7415 in tramp_cerror ()
#6 0x13fda508 in 0x13fda508 ()
#7 0x024f6388 in long long Standard::File::write<unsigned int>(unsigned int const*, long long) at FileIO.h:54
#8 0x024e5fab in SaveFile(std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >, std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >, bool, std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >*) at SaveFile.cpp:4947
#9 0x01c1eeaa in SaveFileThread(void*) at ThreadAny.cpp:103
#10 0x01afe81d in PThread::execute() at PThread.cpp:129
#11 0x01ac7c95 in PThread::run() at POSIXThread.cpp:91
#12 0x01ac7d8a in PThread::threadFunction(void*) at POSIXThread.cpp:131
#13 0x07287928 in _pthread_body ()
#14 0x0728789e in _pthread_start ()
#15 0x07284f2e in thread_start ()

Segmentation fault in malloc_consolidate (malloc.c) that valgrind doesn't detect [duplicate]

This question already has answers here:
Segfaults in malloc() and malloc_consolidate()
(2 answers)
Closed 7 years ago.
My program goes in segmentation faults, and I cannot find the cause.
The worst part is, the function in question does not always lead to segfault.
GDB confirms the bug and yields this backtrace:
Program received signal SIGSEGV, Segmentation fault.
0xb7da6d6e in malloc_consolidate (av=<value optimized out>) at malloc.c:5169
5169 malloc.c: No such file or directory.
in malloc.c
(gdb) bt
#0 0xb7da6d6e in malloc_consolidate (av=<value optimized out>) at malloc.c:5169
#1 0xb7da9035 in _int_malloc (av=<value optimized out>, bytes=<value optimized out>) at malloc.c:4373
#2 0xb7dab4ac in __libc_malloc (bytes=525) at malloc.c:3660
#3 0xb7f8dc15 in operator new(unsigned int) () from /usr/lib/i386-linux-gnu/libstdc++.so.6
#4 0xb7f72db5 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/i386-linux-gnu/libstdc++.so.6
#5 0xb7f740bf in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::_Rep::_M_clone(std::allocator<char> const&, unsigned int) ()
from /usr/lib/i386-linux-gnu/libstdc++.so.6
#6 0xb7f741f1 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::reserve(unsigned int) () from /usr/lib/i386-linux-gnu/libstdc++.so.6
#7 0xb7f6bfec in std::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> >::overflow(int) () from /usr/lib/i386-linux-gnu/libstdc++.so.6
#8 0xb7f70e1c in std::basic_streambuf<char, std::char_traits<char> >::xsputn(char const*, int) () from /usr/lib/i386-linux-gnu/libstdc++.so.6
#9 0xb7f5b498 in std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert_int<unsigned long>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, unsigned long) const () from /usr/lib/i386-linux-gnu/libstdc++.so.6
#10 0xb7f5b753 in std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::do_put(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, unsigned long) const () from /usr/lib/i386-linux-gnu/libstdc++.so.6
#11 0xb7f676ac in std::basic_ostream<char, std::char_traits<char> >& std::basic_ostream<char, std::char_traits<char> >::_M_insert<unsigned long>(unsigned long) ()
from /usr/lib/i386-linux-gnu/libstdc++.so.6
#12 0xb7f67833 in std::basic_ostream<char, std::char_traits<char> >::operator<<(unsigned int) () from /usr/lib/i386-linux-gnu/libstdc++.so.6
#13 0x08049c42 in sim::Address::GetS (this=0xbfffec40) at address.cc:27
#14 0x0806a499 in sim::UserGenerator::ProcessEvent (this=0x80a1af0, e=...) at user-generator.cc:59
#15 0x0806694b in sim::Simulator::CommunicateEvent (this=0x809f970, e=...) at simulator.cc:144
#16 0x0806685d in sim::Simulator::ProcessNextEvent (this=0x809f970) at simulator.cc:133
#17 0x08065d76 in sim::Simulator::Run (seed=0) at simulator.cc:53
#18 0x0807ce85 in main (argc=1, argv=0xbffff454) at main.cc:75
(gdb) f 13
#13 0x08049c42 in sim::Address::GetS (this=0xbfffec40) at address.cc:27
27 oss << m_address;
(gdb) p this->m_address
$1 = 1
Method GetS of class Address translates a number (uint32_t m_address) into a string and returns it. The code (very simple) is the following:
std::string
Address::GetS () const
{
std::ostringstream oss;
oss << m_address;
return oss.str ();
}
Besides, as can be seen in the backtrace, m_address is properly defined.
Now, I have tried to run my program using valgrind.
The program doesn't crash, likely due to the fact that valgrind replaces malloc () among other functions.
The error summary shows no memory leaking:
LEAK SUMMARY:
definitely lost: 0 bytes in 0 blocks
indirectly lost: 0 bytes in 0 blocks
possibly lost: 4,367 bytes in 196 blocks
still reachable: 9,160 bytes in 198 blocks
suppressed: 0 bytes in 0 blocks
All possibly lost refer to backtraces like this:
80 bytes in 5 blocks are possibly lost in loss record 3 of 26
at 0x4024B64: operator new(unsigned int) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
by 0x40DBDB4: std::string::_Rep::_S_create(unsigned int, unsigned int, std::allocator<char> const&) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16)
by 0x40DE077: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16)
by 0x40DE1E5: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16)
by 0x806AF62: sim::UserGenerator::CreateUser(unsigned int) (user-generator.cc:152)
I don't think this is related to the bug. However, the code in question can be found following this link.
I am thinking of a bug in libstdc++. However, how likely would that be?
I have also upgraded such library. Here's the versions currently installed on my system.
$ dpkg -l | grep libstdc
ii libstdc++5 1:3.3.6-23 The GNU Standard C++ Library v3
ii libstdc++6 4.6.1-1 GNU Standard C++ Library v3
ii libstdc++6-4.1-dev 4.1.2-27 The GNU Standard C++ Library v3 (development files)
ii libstdc++6-4.3-dev 4.3.5-4 The GNU Standard C++ Library v3 (development files)
ii libstdc++6-4.4-dev 4.4.6-6 GNU Standard C++ Library v3 (development files)
ii libstdc++6-4.5-dev 4.5.3-3 The GNU Standard C++ Library v3 (development files)
ii libstdc++6-4.6-dev 4.6.1-1 GNU Standard C++ Library v3 (development files)
Now the thing is, I am not sure which version g++ uses, and whether there's some means to enforce the use of a particular version.
What I am pondering is to modify GetS. But this is the only method I know. Do you suggest any alternative?
Eventually, I am even considering to replace std::string with simpler char*.
Maybe a little drastic, but I wouldn't set it aside.
Any thought in merit?
Thank you all in advance.
Best,
Jir
Ok. This is NOT the problem:
I am thinking of a bug in libstdc++
The problem is that you overwrote some memory buffer and corrupted one of the structures used by the memory manager. The hard part is going to be finding it. Does not valgrind give you information about writting past the end of an allocated piece of memory.
Don't do this:
Eventually, I am even considering to replace std::string with simpler char*. Maybe a little drastic, but I wouldn't set it aside.
You already have enough problems with memory management. This will just add more problems. There is absolutely NOTHING wrong with std::string or the memory management routines. They are heavily tested and used. If there was something wrong people all over the world would start screaming (it would be big news).
Reading your code at http://mercurial.intuxication.org/hg/lte_sim/file/c2ef6e0b6d41/src/ it seems like you are still stuck in a C style of writting code (C with Classes). So you have the power of C++ to automate (the blowing up of your code) but still have all the problems associated with C.
You need to re-look at your code in terms of ownership. You pass things around by pointer way too much. As a result it is hard to follow the ownership of the pointer (and thus who is responsible for deleting it).
I think you best bet at finding the bug is to write unit tests for each class. Then run the unit tests through val-grind. I know its a pain (but you should have done it to start with now you have the pain all in one go).