如何在gdb中判断std::字符串是否已被破坏

如何在gdb中判断std::字符串是否已被破坏,gdb,Gdb,我正在调试一个内核转储,当我复制一个std::string时,我的应用程序似乎已经内核化了。sting的内容看起来有点损坏,因此崩溃要么是因为在复制之前字符串被破坏,要么是因为其他一些代码覆盖了字符串的一部分。在gdb中,是否可以判断该字符串是否仍然存在(因此其内存被覆盖),或者在复制之前该字符串是否已被破坏?如果您使用gcc中的gcc和std::string(例如,不是从STLport中使用的)然后,在std::string中有一个内部结构,它保存着_M_refcount,在销毁后该值低于零(

我正在调试一个内核转储,当我复制一个std::string时,我的应用程序似乎已经内核化了。sting的内容看起来有点损坏,因此崩溃要么是因为在复制之前字符串被破坏,要么是因为其他一些代码覆盖了字符串的一部分。在gdb中,是否可以判断该字符串是否仍然存在(因此其内存被覆盖),或者在复制之前该字符串是否已被破坏?

如果您使用gcc中的gcc和std::string(例如,不是从STLport中使用的)然后,在std::string中有一个内部结构,它保存着_M_refcount,在销毁后该值低于零(以下是俄文的详细解释和一些数字:

这来自gcc 4.3.3中的basic_string.h:

        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()); }

正如您在销毁后看到的,0x601020处的值变为0x00000000FFFFFF。_M_refcount的长度为四个字节,因此它是FFFFFF(-1)销毁后。

如果您在Linux上,是否可以在
valgrind
下再次运行您的程序?调试器不是某种mirracle工作程序。析构函数只是一个函数,调试器无法告诉您是否为特定的“this”调用过它,因此,如果析构函数本身没有将任何内容标记为已删除,则您无法删除确保它没有被调用(至少不是由核心转储调用-当然,运行时条件断点可以帮助您,如果您可以重现一个bug),但如果字符串(char数组)实际上已经被覆盖了-希望refcount不被覆盖似乎不太合理。不管它的值如何,它都不能确认任何内容,是吗?除了refcount,还有其他字段,dan可以检查它们(_M_长度和_M_容量和_M_p)当然,这并不能证明覆盖没有发生。然而,我的回答主要是关于std::string的销毁。我还建议在
valgrind
下再次运行该程序。当然,我并不反对你的回答。它很棒而且准确,只是不能完全信任(我指的不是答案本身,而是参考计数,ofc。)然而,即使这个bug无法复制,
valgrind
的memcheck可能会发现一些明显的错误,并可能找到确切的问题,即使出于某些原因,它还没有被注意到。正如我之前所说,我看不到有办法100%肯定析构函数是由崩溃转储单独调用的,主要是因为很难查看过去的e如果没有日志,则进行通风。
#include <string>
#include <stdio.h>

int main()
{
  {
    std::string s1("ABCDEFGHIJKLMNOPRSTUF1234567890");
    printf("Before destruction\n");
  }
  return 0;
}
>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'