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.
Related
I am learning about copy constructor and shallow and deep copy. I was following this video: Copying and Copy Constructors in C++
The following code is copied directly from the video and demonstrates shallow copying... (at 9:30 in the video)
This code is supposed to crash after running because the deconstructor will try to deallocate the same memory twice (first for string and later for string2). The first deletion should work fine but the second one should cause the program to crash as we are trying to delete unallocated memory.
Surprisingly, this doesn't happen in my case. I complied code in my command prompt using g++ copying_and_copy_constructor.cpp and it compiled fine and ran it using a.exe. No errors.
#include<iostream>
#include<cstring>
#include<string>
using std::endl;
using std::cout;
class String
{
private:
char* m_Buffer;
unsigned int m_size;
public:
String(const char* string)
{
m_size = strlen(string);
m_Buffer = new char[m_size+1];
memcpy(m_Buffer,string,m_size);
m_Buffer[m_size] = 0;
}
~String()
{
delete [] m_Buffer;
}
friend std::ostream& operator << (std::ostream& stream, const String& string);
};
std::ostream& operator<<(std::ostream& stream, const String& string)
{
stream<< string.m_Buffer;
return stream;
}
int main()
{
String string = "My string";
String string2 = string;
cout<<string2<<endl;
cout<<string;
return 0;
}
I even tried checking in the debugger. I compiled the code using g++ -g copying_and_copy_constructor.cpp and then gdb a.exe. Here is the output of that:
GNU gdb (GDB) 7.6.1
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "mingw32".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from D:\a.exe...done.
(gdb) start
Temporary breakpoint 1 at 0x401446: file copying_and_copy_constructor.cpp, line 43.
Starting program: D:\a.exe
[New Thread 44892.0x8258]
[New Thread 44892.0x6df8]
[New Thread 44892.0xadd8]
[New Thread 44892.0x9658]
Temporary breakpoint 1, main () at copying_and_copy_constructor.cpp:43
43 String string = "My string";
(gdb) c
Continuing.
My string
My string[Inferior 1 (process 44892) exited normally]
(gdb)
The program is not being run.
(gdb) q
This line confuses me My string[Inferior 1 (process 44892) exited normally]. How is this code is exiting normally?
The person in the video is using VS-Code... How can I get the same error in the command prompt?
Crash as shown in the video:
(I don't have vs code as of now (might install it later))
For me (Fedora 32 x86_64) it does crash:
$ g++ -o q q.C -Wall -g;./q
My string
free(): double free detected in tcache 2
Aborted
But I definitely agree such code may look running fine. This is why there is ASAN:
$ g++ -o q q.C -Wall -g -fsanitize=address;./q
My string
=================================================================
==3388436==ERROR: AddressSanitizer: attempting double-free on 0x602000000010 in thread T0:
#0 0x7fb76f262cd7 in operator delete[](void*) (/lib64/libasan.so.6+0xb2cd7)
#1 0x4016e9 in String::~String() /home/jkratoch/t/q.C:25
#2 0x40144b in main /home/jkratoch/t/q.C:42
#3 0x7fb76ecbc041 in __libc_start_main ../csu/libc-start.c:308
#4 0x40120d in _start (/quad/home/jkratoch/t/q+0x40120d)
0x602000000010 is located 0 bytes inside of 10-byte region [0x602000000010,0x60200000001a)
freed by thread T0 here:
#0 0x7fb76f262cd7 in operator delete[](void*) (/lib64/libasan.so.6+0xb2cd7)
#1 0x4016e9 in String::~String() /home/jkratoch/t/q.C:25
#2 0x40143e in main /home/jkratoch/t/q.C:43
#3 0x7fb76ecbc041 in __libc_start_main ../csu/libc-start.c:308
previously allocated by thread T0 here:
#0 0x7fb76f2621d7 in operator new[](unsigned long) (/lib64/libasan.so.6+0xb21d7)
#1 0x4015d6 in String::String(char const*) /home/jkratoch/t/q.C:18
#2 0x4013a0 in main /home/jkratoch/t/q.C:42
#3 0x7fb76ecbc041 in __libc_start_main ../csu/libc-start.c:308
SUMMARY: AddressSanitizer: double-free (/lib64/libasan.so.6+0xb2cd7) in operator delete[](void*)
==3388436==ABORTING
In the case you do not want or even cannot recompile the program with -fsanitize=address you can use Valgrind (but it is slower and it does not detect everything):
$ g++ -o q q.C -Wall -g;valgrind ./q
==3388447== Memcheck, a memory error detector
==3388447== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==3388447== Using Valgrind-3.16.0 and LibVEX; rerun with -h for copyright info
==3388447== Command: ./q
==3388447==
My string
==3388447== Invalid free() / delete / delete[] / realloc()
==3388447== at 0x483C59C: operator delete[](void*) (vg_replace_malloc.c:649)
==3388447== by 0x40139E: String::~String() (q.C:25)
==3388447== by 0x401277: main (q.C:42)
==3388447== Address 0x4db5c80 is 0 bytes inside a block of size 10 free'd
==3388447== at 0x483C59C: operator delete[](void*) (vg_replace_malloc.c:649)
==3388447== by 0x40139E: String::~String() (q.C:25)
==3388447== by 0x40126B: main (q.C:43)
==3388447== Block was alloc'd at
==3388447== at 0x483B582: operator new[](unsigned long) (vg_replace_malloc.c:431)
==3388447== by 0x401334: String::String(char const*) (q.C:18)
==3388447== by 0x40121B: main (q.C:42)
==3388447==
My string==3388447==
==3388447== HEAP SUMMARY:
==3388447== in use at exit: 0 bytes in 0 blocks
==3388447== total heap usage: 3 allocs, 4 frees, 73,738 bytes allocated
==3388447==
==3388447== All heap blocks were freed -- no leaks are possible
==3388447==
==3388447== For lists of detected and suppressed errors, rerun with: -s
==3388447== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
I'm getting a segmentation fault on code that looks perfectly valid to me.
Here's a minimal recreating example:
#include <iostream>
#include <thread>
void func()
{
/* do nothing; thread contents are irrelevant */
}
int main()
{
for (unsigned idx = 0; idx < 1000; idx++)
{
std::thread t(func);
void* buffer = malloc(1000);
free(buffer);
t.join();
}
return 0;
}
I made a run with prints, to check which iteration fails; I got the segmentation fault on iteration #292.
I used gcc-linaro-4.9.4 (taken from here: https://releases.linaro.org/components/toolchain/binaries/4.9-2017.01/arm-linux-gnueabihf/).
I compiled the program this way:
arm-linux-gnueabihf-g++ -std=c++11 -std=gnu++11 -lpthread -pthread main.cpp -o main.out
I tried recreating this in gcc-linaro-6.5, and didn't have the problem there.
Any idea why this happens?
Edit 1
There is no warnings/errors when I compile this code.
Running it under strace reveals nothing special.
Running it under GDB reveals that the segmentation faults happens in free function:
Thread 1 "main.out" received signal SIGSEGV, Segmentation fault.
_int_free (av=0x76d84794 <main_arena>, p=0x1e8bf, have_lock=0) at malloc.c:4043
4043 malloc.c: No such file or directory.
(gdb) bt
#0 _int_free (av=0x76d84794 <main_arena>, p=0x1e8bf, have_lock=0) at malloc.c:4043
#1 0x00010bfa in main ()
Running it under valgrind reveals the following:
==361== Thread 2:
==361== Invalid read of size 4
==361== at 0x4951D64: ??? (in /usr/lib/arm-linux-gnueabihf/libstdc++.so.6.0.22)
==361== Address 0x4becf74 is 0 bytes after a block of size 28 alloc'd
==361== at 0x4847D4C: operator new(unsigned int) (vg_replace_malloc.c:328)
==361== by 0x11629: __gnu_cxx::new_allocator<std::_Sp_counted_ptr_inplace<std::thread::_Impl<std::_Bind_simple<void (*())()> >, std::allocator<std::thread::_Impl<std::_Bind_simple<void (*())()> > >, (__gnu_cxx::_Lock_policy)2> >::allocate(unsigned int, void const*) (in /home/pi/main.out)
==361==
==361== Invalid write of size 4
==361== at 0x4951D6C: ??? (in /usr/lib/arm-linux-gnueabihf/libstdc++.so.6.0.22)
==361== Address 0x4becf74 is 0 bytes after a block of size 28 alloc'd
==361== at 0x4847D4C: operator new(unsigned int) (vg_replace_malloc.c:328)
==361== by 0x11629: __gnu_cxx::new_allocator<std::_Sp_counted_ptr_inplace<std::thread::_Impl<std::_Bind_simple<void (*())()> >, std::allocator<std::thread::_Impl<std::_Bind_simple<void (*())()> > >, (__gnu_cxx::_Lock_policy)2> >::allocate(unsigned int, void const*) (in /home/pi/main.out)
==361==
==361==
==361== HEAP SUMMARY:
==361== in use at exit: 28,000 bytes in 1,000 blocks
==361== total heap usage: 2,002 allocs, 1,002 frees, 1,048,368 bytes allocated
==361==
==361== Thread 1:
==361== 28,000 bytes in 1,000 blocks are definitely lost in loss record 1 of 1
==361== at 0x4847D4C: operator new(unsigned int) (vg_replace_malloc.c:328)
==361== by 0x11629: __gnu_cxx::new_allocator<std::_Sp_counted_ptr_inplace<std::thread::_Impl<std::_Bind_simple<void (*())()> >, std::allocator<std::thread::_Impl<std::_Bind_simple<void (*())()> > >, (__gnu_cxx::_Lock_policy)2> >::allocate(unsigned int, void const*) (in /home/pi/main.out)
==361==
==361== LEAK SUMMARY:
==361== definitely lost: 28,000 bytes in 1,000 blocks
==361== indirectly lost: 0 bytes in 0 blocks
==361== possibly lost: 0 bytes in 0 blocks
==361== still reachable: 0 bytes in 0 blocks
==361== suppressed: 0 bytes in 0 blocks
==361==
==361== For counts of detected and suppressed errors, rerun with: -v
==361== ERROR SUMMARY: 2017 errors from 3 contexts (suppressed: 6 from 3)
edit 2
I still get segmetation fault after I remove the -lpthread and -std=c++11 compilation flags. This is the way I compiled it this time:
arm-linux-gnueabihf-g++ -std=gnu++11 -pthread main.cpp -o main.out
I think the problem is a mismatch between your code and the libstdc++.so library you're linking to.
One possibility is that the wrong libstdc++.so is being used at runtime, which you could check by using the ldd utility. The correct version for GCC 4.9.4 is libstdc++.so.6.0.20 so if you see it linking to a different version, that's a problem.
The second possibility is that it's the right libstdc++.so but it is compiled with different settings from your code, and so the std::thread in your code uses atomic operations for shared_ptr reference counting, but the std::thread in the library uses a mutex (which is the same problem as described in GCC Bug 42734). If the crash and the valgrind errors go away when you compile your program with -march=armv5t then it would confirm this is the problem.
I have build executable for below program with PPC toolchain.
Tool chain details:
powerpc-wrs-linux-gnu-g++ (Wind River Linux Sourcery G++ 4.4a-341) 4.4.1
We have included -pthread during compilation and -lpthread for linking. We are using -lrt and -ldl flags too.
#include <string>
#include <iostream>
#include <thread>
using namespace std;
// The function we want to execute on the new thread.
void task1(string msg)
{
cout << "task1 says: " << msg;
}
int main()
{
// Constructs the new thread and runs it. Does not block execution.
thread t1(task1, "Hello");
// Makes the main thread wait for the new thread to finish execution
// therefore blocks its own execution.
t1.join();
}
While executing the program am getting the crash as below
Program received signal SIGILL, Illegal instruction.
0x10000e30 in __gnu_cxx::__exchange_and_add(int volatile*, int) ()
(gdb) bt
#0 0x10000e30 in __gnu_cxx::__exchange_and_add(int volatile*, int) ()
#1 0x10000f14 in __gnu_cxx::__exchange_and_add_dispatch(int*, int) ()
#2 0x10001960 in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() ()
#3 0x100016ac in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() ()
#4 0x100013ac in std::__shared_ptr<std::thread::_Impl_base, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() ()
#5 0x100013e8 in std::shared_ptr<std::thread::_Impl_base>::~shared_ptr() ()
#6 0x100014c0 in std::thread::thread<void (&)(std::basic_string<char, std::char_traits<char>, std::allocator<char> >), char const (&) [6]>(void (&&&)(std::basic_string<char, std::char_traits<char>, std::allocator<char> >), char const (&&&) [6]) ()
#7 0x10000fd4 in main ()
Can you please suggest are we missing something in flags for build.
There is one obvious bug in your code
cout << "task1 says: " << msg;
here cout (stream) is shared resource , you should synchronize access to it.
The main hint is here:
Program received signal SIGILL, Illegal instruction.
It looks like the default code generation settings of your compiler are outputting instructions that are not supported by your CPU. If you print the actual faulting instruction from gdb, you can get more detail about the problem. Try:
(gdb) x /i $pc
To see the exact instruction causing the SIGILL.
Since the illegal instruction is in __exchange_and_add, it's likely that this will be one of the atomic storage instructions.
To fix this, you will probably want to tell your compiler which CPU to generate instructions for. You can do this with the -mcpu= argument. If you give an invalid cpu specifier, gcc will print the available CPU types:
$ powerpc64le-linux-gnu-gcc -mcpu=?
powerpc64le-linux-gnu-gcc: error: unrecognized argument in option ‘-mcpu=?’
powerpc64le-linux-gnu-gcc: note: valid arguments to ‘-mcpu=’ are: 401 403 405 405fp 440 440fp 464 464fp 476 476fp 505 601 602 603 603e 604 604e 620 630 740 7400 7450 750 801 821 823 8540 8548 860 970 G3 G4 G5 a2 cell e300c2 e300c3 e500mc e500mc64 e5500 e6500 ec603e native power3 power4 power5 power5+ power6 power6x power7 power8 power9 powerpc powerpc64 powerpc64le rs64 titan
powerpc64le-linux-gnu-gcc: fatal error: no input files
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?
Here's a test program which leaks (on Ubuntu 10.04, ICU 4.2):
#include <unicode/uversion.h>
#include <unicode/calendar.h>
int main()
{
TimeZone* tz = TimeZone::createTimeZone("Asia/Pyongyang");
UErrorCode status = U_ZERO_ERROR;
Calendar* cal = Calendar::createInstance(tz, status); // adopts tz
delete cal;
}
valgrind --leak-check=full says:
==22978== 304 bytes in 1 blocks are possibly lost in loss record 20 of 22
==22978== at 0x4C28F86: malloc (vg_replace_malloc.c:291)
==22978== by 0x526B34D: icu_4_2::UnicodeString::allocate(int) (in /usr/lib/libicuuc.so.42.1)
==22978== by 0x526B993: icu_4_2::UnicodeString::cloneArrayIfNeeded(int, int, signed char, int**, signed char) (in /usr/lib/libicuuc.so.42.1)
==22978== by 0x526D97A: icu_4_2::UnicodeString::doReplace(int, int, unsigned short const*, int, int) (in /usr/lib/libicuuc.so.42.1)
==22978== by 0x4EF0E90: icu_4_2::TimeZone::initDefault() (in /usr/lib/libicui18n.so.42.1)
==22978== by 0x4EF10A4: icu_4_2::TimeZone::createDefault() (in /usr/lib/libicui18n.so.42.1)
==22978== by 0x4EEE750: icu_4_2::GregorianCalendar::GregorianCalendar(icu_4_2::Locale const&, UErrorCode&) (in /usr/lib/libicui18n.so.42.1)
==22978== by 0x4EEB493: ??? (in /usr/lib/libicui18n.so.42.1)
==22978== by 0x4EEBA01: icu_4_2::Calendar::createInstance(icu_4_2::TimeZone*, icu_4_2::Locale const&, UErrorCode&) (in /usr/lib/libicui18n.so.42.1)
==22978== by 0x400A42: icu_4_2::Calendar::createInstance(icu_4_2::TimeZone*, UErrorCode&) (in /home/jzwinck/test/a.out)
==22978== by 0x4009C5: main
My question is, am I using ICU incorrectly, or is there some workaround I can apply to free the default time zone object which ICU seems to be creating? I can't easily change the versions of OS and ICU I'm using.
You need to call u_cleanup() to clean up ICU. Usually it doesn't matter, so is not done automatically. If you build ICU with --enable-auto-cleanup it will attempt to cleanup when the library unloads, on some platforms. See the userguide.