Reputation: 1615
I am debugging a core dump and it seems my app has cored when making a copy of a std::string. The contents of the sting look a little corrupted, so the crash is either due to the string having been destructed before the copy, or because some other code has overwritten part of the string. Is it possible in gdb to tell if the string still exists (and therefore has had its memory overwritten) or if the string has been destructed previous to the copy?
Upvotes: 0
Views: 750
Reputation:
If you use gcc and std::string from gcc (and not from STLport for example) then there is an internal structure inside std::string that holds _M_refcount which is below zero after destruction (Here is in russian a detailed explanation with some figures "Несколько подробностей об std::string":
This is from basic_string.h from gcc 4.3.3:
void
_M_dispose(const _Alloc& __a)
{
#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
if (__builtin_expect(this != &_S_empty_rep(), false))
#endif
if (__gnu_cxx::__exchange_and_add_dispatch(&this->_M_refcount,
-1) <= 0)
_M_destroy(__a);
} // XXX MT
~basic_string()
{ _M_rep()->_M_dispose(this->get_allocator()); }
So this is a simple test:
#include <string>
#include <stdio.h>
int main()
{
{
std::string s1("ABCDEFGHIJKLMNOPRSTUF1234567890");
printf("Before destruction\n");
}
return 0;
}
Compiled and built:
g++ -m64 -g -pthread main.cpp
And this is under gdb:
>gdb -q ./a.out
(gdb) start
Temporary breakpoint 1 at 0x400787: file main.cpp, line 7.
[Thread debugging using libthread_db enabled]
Temporary breakpoint 1, main () at main.cpp:7
7 std::string s1("ABCDEFGHIJKLMNOPRSTUF1234567890");
(gdb) n
8 printf("Before destruction\n");
(gdb) x/4gx (((void**)&s1)[0]-24)
0x601010: 0x000000000000001f 0x000000000000001f
0x601020: 0x0000000000000000 0x4847464544434241
(gdb) x/32c (((void**)&s1)[0])
0x601028: 65 'A' 66 'B' 67 'C' 68 'D' 69 'E' 70 'F' 71 'G' 72 'H'
0x601030: 73 'I' 74 'J' 75 'K' 76 'L' 77 'M' 78 'N' 79 'O' 80 'P'
0x601038: 82 'R' 83 'S' 84 'T' 85 'U' 70 'F' 49 '1' 50 '2' 51 '3'
0x601040: 52 '4' 53 '5' 54 '6' 55 '7' 56 '8' 57 '9' 48 '0' 0 '\000'
(gdb) n
Before destruction
10 return 0;
(gdb) x/4gx (((void**)&s1)[0]-24)
0x601010: 0x0000000000000000 0x000000000000001f
0x601020: 0x00000000ffffffff 0x4847464544434241
(gdb) x/32c (((void**)&s1)[0])
0x601028: 65 'A' 66 'B' 67 'C' 68 'D' 69 'E' 70 'F' 71 'G' 72 'H'
0x601030: 73 'I' 74 'J' 75 'K' 76 'L' 77 'M' 78 'N' 79 'O' 80 'P'
0x601038: 82 'R' 83 'S' 84 'T' 85 'U' 70 'F' 49 '1' 50 '2' 51 '3'
0x601040: 52 '4' 53 '5' 54 '6' 55 '7' 56 '8' 57 '9' 48 '0' 0 '\000'
As you can see after destruction the value at 0x601020 becomes 0x00000000ffffffff. _M_refcount is four bytes long so it is ffffffff (-1) after destruction.
Upvotes: 2