I am using the library Crafter in my c++ program. When calling the function
Crafter::GetMAC("192.168.1.10", "eth0");
I receive a Segmentation Fault, I looked into this method, which calls some other methods. The call stack is as follows:
- Crafter::GetMAC("192.168.1.10", "eth0");
- GetMACIPv4(net_addr, iterator->iface_name);
- Packet::SendRecv(const string& iface, double timeout, int retry, const string& user_filter);
In the SendRecv I receive the Segmentation Fault at this line:
if ((r = pcap_next_ex (handle, &header, &packet)) <= 0)
I run the program with valgrind and the stacktrace output of the error I receive is the following:
==32555== Process terminating with default action of signal 11 (SIGSEGV)
==32555== Access not within mapped region at address 0x0
==32555== at 0x4E68DD0: Crafter::Packet::PacketFromIP(unsigned char const*, unsigned long) (PacketDecoder.cpp:599)
==32555== by 0x406EA2: captureThreadCallback(unsigned char*, pcap_pkthdr const*, unsigned char const*) (NetworkStructure.cpp:17)
==32555== by 0x50CE805: pcap_handle_packet_mmap (pcap-linux.c:4546)
==32555== by 0x50D31D0: pcap_read_linux_mmap_v3 (pcap-linux.c:4825)
==32555== by 0x50D76AC: pcap_loop (pcap.c:868)
==32555== by 0x406F65: captureThread(void*) (NetworkStructure.cpp:35)
==32555== by 0x53120A4: start_thread (pthread_create.c:309)
==32555== by 0x5B47CFC: clone (clone.S:111)
The installed version of libcrafter is 0.2, and from libpcap 1.6.2-1
Does anyone have an idea how to fix this?
Related
I'm using Valgrind and GDB to debug a memory leak. I've the following call trace that shows where the memory leak occurs:
(gdb) monitor block_list 10104
==961== 153 (18 direct, 135 indirect) bytes in 1 blocks are definitely lost in loss record 10,104 of 10,317
==961== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==961== by 0x678199: create_node(unsigned char const*, unsigned int, document*) (a.cpp:436)
==961== by 0x67933A: insert(art_node*, art_node**, unsigned char const*, unsigned int, document*, unsigned int, int, int*) (a.cpp:704)
==961== by 0x68327B: Program::add(std::string const&) (program.cpp:84)
==961== by 0x7220BF: main (main.cpp:52)
I want to print the value of the string argument that's passed to Program::add at:
==961== by 0x68327B: Program::add(std::string const&) (program.cpp:84)
How do I do that in GDB?
You can follow step by step Valgrind manual:
If you want to debug a program with GDB when using the Memcheck tool,
start Valgrind like this:
valgrind --vgdb=yes --vgdb-error=0 prog
In another shell, start GDB:
gdb prog
Then give the following command to GDB:
(gdb) target remote | vgdb
Now you can go to frame Program::add(std::string const&) in gdb and print the value of argument.
I am using a library (C++ REST SDK) in which I can set a handler for a specific event. Precisely I set a close handler which gets called when a websocket connection gets closed by the client(me) or the server. The handler is set like this:
// WebsocketClient is my own custom class
// m_pclClient holds the connection (of type websocket_callback_client)
std::function<void(web::websockets::client::websocket_close_status close_status, const utility::string_t &reason, const std::error_code &error)> handler(std::bind(&WebsocketClient::close_handler, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
this->m_pclClient->set_close_handler(handler);
When I now close the connection the library handles the closing procedure and, after finishing the process, calls handler with its three parameters.
When closing the connection an error occurs. I am not sure if it's a bug inside the library or my mistake. gdb output when closing the connection:
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fffe1c23700 (LWP 13849)]
0x00000000004e20b7 in std::__invoke_impl<void, void (WebsocketClient::* const&)(web::websockets::client::websocket_close_status, std::string const&, std::error_code const&), WebsocketClient*&, web::websockets::client::websocket_close_status, std::string const&, std::error_code const&>(std::__invoke_memfun_deref, void (WebsocketClient::* const&)(web::websockets::client::websocket_close_status, std::string const&, std::error_code const&), WebsocketClient*&, web::websockets::client::websocket_close_status&&, std::string const&, std::error_code const&) (__f=
#0x80d290: (void (WebsocketClient::*)(WebsocketClient * const, web::websockets::client::websocket_close_status, const std::basic_string<char, std::char_traits<char>, std::allocator<char> > &, const std::error_code &)) 0x4cf120 <WebsocketClient::close_handler(web::websockets::client::websocket_close_status, std::string const&, std::error_code const&)>, __t=#0x80d2a0: 0x8081f8,
__args#0=<unknown type in /path/to/executable, CU 0x1d28f4, DIE 0x21f672>, __args#1="TLS Short Read", __args#2=...) at /usr/include/c++/6/functional:235
235 return ((*std::forward<_Tp>(__t)).*__f)(std::forward<_Args>(__args)...);
There's obviously a problem with argument #0: web::websockets::client::websocket_close_status close_status.
It seems that when the handler should be invoked, the type of the first argument is unknown. See in the gdb output: "__args#0= < unknown type in /path/to/executable"
Why is this happening and how to fix it?
this is one of my strangest errors.
QRegularExpression regexp(" .*");
This works fine, sometimes. But than it crashes with segmentation faul.
0 _int_malloc /usr/lib64/libc.so.6 0x7ffff59f2196
1 malloc /usr/lib64/libc.so.6 0x7ffff59f411c
2 operator new(unsigned long) /usr/lib64/libstdc++.so.6 0x7ffff62ac0cd
3 QRegularExpression::QRegularExpression(QString const&, QFlags<QRegularExpression::PatternOption>) /usr/lib64/libQt5Core.so.5 0x7ffff6b45fdd
The Strange thing ist, if i start the program sometimes its okay! No Error at all.
Sometime its crashes after this loc was excecuted excacly 71 times.
I just dont have any clue -.-
EDIT:
char hname[255] ="";
char hname80[255] ="";
char hcas[255] = "";
int i = number;
NAMEdll(i,hname,hname80,hcas);
shortName=hname;
fullName=hname80;
cas=hcas;
// remove unecessary spaces
QRegularExpression regexp(" .*");
cas.remove(regexp);
shortName.remove(regexp);
fullName.remove(regexp)
like suggested i removed code to find the error.
Its seems to have something to do with NAMEdll ( which is a fortran function). If i take out this command, its all fine. With it i get this:
0 _int_malloc /usr/lib64/libc.so.6 0x7ffff59f2196
1 malloc /usr/lib64/libc.so.6 0x7ffff59f411c
2 QArrayData::allocate(unsigned long, unsigned long, unsigned long, QFlags<QArrayData::AllocationOption>) /usr/lib64/libQt5Core.so.5 0x7ffff6a7c0f6
3 QRegularExpressionMatchPrivate::QRegularExpressionMatchPrivate(QRegularExpression const&, QString const&, QRegularExpression::MatchType, QFlags<QRegularExpression::MatchOption>, int) /usr/lib64/libQt5Core.so.5 0x7ffff6b4617a
4 QRegularExpression::match(QString const&, int, QRegularExpression::MatchType, QFlags<QRegularExpression::MatchOption>) const /usr/lib64/libQt5Core.so.5 0x7ffff6b475e4
5 QRegularExpression::globalMatch(QString const&, int, QRegularExpression::MatchType, QFlags<QRegularExpression::MatchOption>) const /usr/lib64/libQt5Core.so.5 0x7ffff6b47c77
6 QString::replace(QRegularExpression const&, QString const&) /usr/lib64/libQt5Core.so.5 0x7ffff6b1c4a9
7 QString::remove qstring.h 429 0x4852fe
Just guessing, but is there a chance that inside the fortran code (its not my ) something can cause a malloc call to fail ? And if it is so, can someone explain how ?
EDIT:
Solved:
Okay i found it by accident.
In a diffrent part of the program i had the following code:
char href[3] ="";
strcpy(href,"DEF");
This is bad, cause strcpy also writes an end character '\0'. So the written chararray has the length of 4.
I recently read about using GCC's code generation features (specifically, the -finstrument-functions compiler flag) to easily add instrumentation to my programs. I thought it sounded really cool and went to try it out on a previous C++ project. After several revisions of my patch, I found that any time I tried to use an STL container or print to stdout using C++ stream I/O, my program would immediately crash with a segfault. My first idea was to maintain a std::list of Event structs
typedef struct
{
unsigned char event_code;
intptr_t func_addr;
intptr_t caller_addr;
pthread_t thread_id;
timespec ts;
}Event;
list<Event> events;
which would be written to a file when the program terminated. GDB told me that when I tried to add an Event to the list, calling events.push_back(ev) itself initiated an instrumentation call. This wasn't terrible surprising and made sense after I thought about it for a bit, so on to plan 2.
The example in the blog which got me involved in all this mess didn't do anything crazy, it simply wrote a string to a file using fprintf(). I didn't think there would be any harm in using C++'s stream-based I/O instead of the older (f)printf(), but that assumption proved to be wrong. This time, instead of a nearly-infinite death spiral, GDB reported a fairly normal-looking descent into the standard library... followed by a segfault.
A Short Example
#include <list>
#include <iostream>
#include <stdio.h>
using namespace std;
extern "C" __attribute__ ((no_instrument_function)) void __cyg_profile_func_enter(void*, void*);
list<string> text;
extern "C" void __cyg_profile_func_enter(void* /* unused */, void* /* unused */)
{
// Method 1
text.push_back("NOPE");
// Method 2
cout << "This explodes" << endl;
// Method 3
printf("This works!");
}
Sample GDB Backtrace
Method 1
#0 _int_malloc (av=0x7ffff7380720, bytes=29) at malloc.c:3570
#1 0x00007ffff704ca45 in __GI___libc_malloc (bytes=29) at malloc.c:2924
#2 0x00007ffff7652ded in operator new(unsigned long) ()
from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3 0x00007ffff763ba89 in std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4 0x00007ffff763d495 in char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5 0x00007ffff763d5e3 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6 0x00000000004028c1 in __cyg_profile_func_enter () at src/instrumentation.cpp:82
#7 0x0000000000402c6f in std::move<std::string&> (__t=...) at /usr/include/c++/4.6/bits/move.h:82
#8 0x0000000000402af5 in std::list<std::string, std::allocator<std::string> >::push_back(std::string&&) (this=0x6055c0, __x=...) at /usr/include/c++/4.6/bits/stl_list.h:993
#9 0x00000000004028d2 in __cyg_profile_func_enter () at src/instrumentation.cpp:82
#10 0x0000000000402c6f in std::move<std::string&> (__t=...) at /usr/include/c++/4.6/bits/move.h:82
#11 0x0000000000402af5 in std::list<std::string, std::allocator<std::string> >::push_back(std::string&&) (this=0x6055c0, __x=...) at /usr/include/c++/4.6/bits/stl_list.h:993
#12 0x00000000004028d2 in __cyg_profile_func_enter () at src/instrumentation.cpp:82
#13 0x0000000000402c6f in std::move<std::string&> (__t=...) at /usr/include/c++/4.6/bits/move.h:82
#14 0x0000000000402af5 in std::list<std::string, std::allocator<std::string> >::push_back(std::string&
...
Method 2
#0 0x00007ffff76307d1 in std::ostream::sentry::sentry(std::ostream&) ()
from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#1 0x00007ffff7630ee9 in std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long) ()
from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#2 0x00007ffff76312ef in std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*) ()
from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3 0x000000000040251e in __cyg_profile_func_enter () at src/instrumentation.cpp:81
#4 0x000000000040216d in _GLOBAL__sub_I__ZN8GLWindow7attribsE () at src/glwindow.cpp:164
#5 0x0000000000402f2d in __libc_csu_init ()
#6 0x00007ffff6feb700 in __libc_start_main (main=0x402cac <main()>, argc=1, ubp_av=0x7fffffffe268,
init=0x402ed0 <__libc_csu_init>, fini=<optimized out>, rtld_fini=<optimized out>,
stack_end=0x7fffffffe258) at libc-start.c:185
#7 0x0000000000401589 in _start ()
Environment:
Ubuntu Linux 12.04 (x64)
GCC 4.6.3
Intel 3750K CPU
8GB RAM
The problem with using cout in the instrumentation function is that the instrumentation function is being called by __libc_csu_init() which is a very early part of the runtime's initialization - before global C++ objects get a chance to be constructed (in fact, I think __libc_csu_init() is responsible for kicking off those constructors - at least indirectly).
So cout hasn't had a chance to be constructed yet and trying to use it doesn't work very well...
And that may well be the problem you run into with trying to use std::List after fixing the infinite recursion (mentioned in Dave S' answer).
If you're willing to lose some instrumentation during initialization, you can do something like:
#include <iostream>
#include <stdio.h>
int initialization_complete = 0;
using namespace std;
extern "C" __attribute__ ((no_instrument_function)) void __cyg_profile_func_enter(void*, void*);
extern "C" void __cyg_profile_func_enter(void* /* unused */, void* /* unused */)
{
if (!initialization_complete) return;
// Method 2
cout << "This explodes" << endl;
// Method 3
printf("This works! ");
}
void foo()
{
cout << "foo()" << endl;
}
int main()
{
initialization_complete = 1;
foo();
}
The first case seems to be an infinite loop, resulting in stack overflow. This is probably because std::list is a template, and it's code is generated as part of the translation unit where you're using it. This causes it to get instrumented as well. So you call push_back, which calls the handler, which calls push_back, ...
The second, if I had to guess, might be similar, though it's harder to tell.
The solution is to compile the instrumentation functions separately, without the -finstrument-functions. Note, the example blog compiled the trace.c separately, without the option.
I am writing an application that uses pion library and notice a crash when I try to send a request. The crash is happening due to segmentation fault. This is in Linux and I am linking with PION_FULL.
Code:
pion::net::HTTPRequest httpRequest("/sm_login/trusted.asp?app-id=test");
int port = 80;
httpRequest.setMethod("GET");
httpRequest.addHeader("Host", "127.0.0.1");
pion::net::TCPConnection connPtr(IO_service);
error = connPtr.connect(boost::asio::ip::address::from_string("127.0.0.1"), port);
if (error || !connPtr.is_open())
{
dprintf(("Unable to establish connection"));
return false;
}
httpRequest.send(connPtr, error);
Dump:
#0 0x0eec4bb4 in void pion::net::HTTPMessage::changeValue<std::tr1::unordered_multimap<std::string, std::string, CaseInsensitiveHash, CaseInsensitiveEqual, std::allocator<std::pair<std::string const, std::string> > >
>(std::tr1::unordered_multimap<std::string, std::string, CaseInsensitiveHash, CaseInsensitiveEqual, std::allocator<std::pair<std::string const, std::string> > >&, std::string const&, std::string const&) () from /sw/lib/libpion-net-2.2.12.so
#1 0x0eec11f0 in pion::net::HTTPMessage::send(pion::net::TCPConnection&, boost::system::error_code&) () from /sw/lib/libpion-net-2.2.12.so
#2 0x0f1e6c24 in CHeapInterface::SendRequest(std::string const&, std::string&, CHeapInterface::EHeapMsgType) () from /sw/lib/libMgmt.so
Thanks,
The problem was due to mismatch in cross compiler version used to build pion libs. The application is not crashing anymore.