dan
dan

Reputation: 1615

how to tell in gdb if a std::string has been destructed

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

Answers (1)

user184968
user184968

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

Related Questions