c++ - gdb 显示类成员的乱码值,尽管代码有效

标签 c++ debugging gdb initialization

今天我遇到了一个(在我看来)非常奇怪的 gdb 问题,同时试图编写一个更像 C++ 的 reverse() 版本。我的字符串类的方法(当然都是为了学习)。尽管有一个适当的默认构造函数将所有成员变量初始化为 0,但它们在成员 reverse() 中开始时是乱码。 - 根据 gdb(除调试之外的所有功能实际上都运行良好)- 但不是在只创建空字符串的基本程序中。这可能与 reverse() 的事实有关吗?是创建自己类实例的成员函数吗?如果不是,为什么它不会发生在基本程序中?

顺便说一句,在我提到任何代码之前:我是这样编译的:

g++ -c -o tests.o tests.cpp -Wall -Werror -DDEBUG=0 -O0 -ggdb3
g++ -c -o string.o string.cpp -Wall -Werror -DDEBUG=0 -O0 -ggdb3
g++ -o tests tests.o string.o -Wall -Werror -DDEBUG=0 -O0 -ggdb3

代码:

string::string() : buf(NULL), _length(0), _size(0) {
    init();
}

/* This is redundant in this case (right?), but the function is used elsewhere,
   and I added the above initialization list while debugging this. */
void string::init() {
    this->buf = NULL;
    this->_length = 0;
    this->_size = 0;
}

string string::reverse(void) const {
    string rev;
    rev.alloc(this->_length + 1);

    for (size_t i=0; i<this->_length; i++) {
    ...

以下是我通过 gdb 7.0(在 Linux 上)运行上述命令得到的结果:
(对不起,水平滚动,但这并不重要,因为无论如何您都可以看到您需要的一切。)

Breakpoint 1, exscape::string::reverse (this=0x7fffffffd580) at string.cpp:368
368                     string rev;
(gdb) next
378                     rev.alloc(this->_length + 1); <<<< not yet executed when we print below!
(gdb) p rev
$1 = {buf = 0x7fffffffd560 "", _length = 140737488344448, _size = 140737488344128}
(gdb) n
380                     for (size_t i=0; i<this->_length; i++) {
(gdb) 
381                             rev.buf[this->_length-i-1] = this->buf[i];
380                     for (size_t i=0; i<this->_length; i++) {
(gdb) p rev
$2 = {buf = 0x7fffffffd560 "P\321`", _length = 140737488344448, _size = 140737488344128}
(gdb) n
381                             rev.buf[this->_length-i-1] = this->buf[i];
(gdb) 
380                     for (size_t i=0; i<this->_length; i++) {
...
384                     rev._length = this->_length;
(gdb) 
386             }
(gdb) p rev
$3 = {buf = 0x7fffffffd560 "P\321`", _length = 140737488344448, _size = 140737488344128}
(gdb) next
main () at tests.cpp:72
(gdb) p r2 <<<< r2 is the name of the variable returned by reverse() of course
$4 = {buf = 0x60d150 "ABCDEF", _length = 6, _size = 7}

为什么成员变量在 gdb 中似乎以乱码结尾? (乱码值总是非常接近 this,顺便说一下!在本次运行中,this == 0x7fffffffd580 == 140737488344448,与 _length 的值相同)。该函数完美运行,valgrind 从不提示,一切都很好......直到我尝试重写该方法并且无法正确调试它,也就是说。

有什么建议吗?

更新:调用函数的示例程序:

#include <iostream>
#include "string.hpp"
int main() {
    exscape::string s("Hello, world!");
    exscape::string s2; // Use the default constructor
    s2 = s.reverse();
    std::cout << "Reversed: " << s2 << std::endl;

    return 0;
}

(gdb) break exscape::string::reverse
Breakpoint 1 at 0x402ed6: file string.cpp, line 368.
(gdb) run
Starting program: /home/serenity/programming/cpp/string/a.out 

Breakpoint 1, exscape::string::reverse (this=0x7fffffffdc80) at string.cpp:368
368                     string rev;
(gdb) n
378                     rev.alloc(this->_length + 1);
(gdb) p rev
$1 = {buf = 0x7fffffffdca0 "", _length = 140737488346240, _size = 140737488346208}
(gdb) finish
Run till exit from #0  exscape::string::reverse (this=0x7fffffffdc80) at string.cpp:378
0x000000000040163f in main () at bare.cpp:6
6               s2 = s.reverse();
Value returned is $2 = {buf = 0x607030 "!dlrow ,olleH", _length = 13, _size = 14}
(gdb) n
7               std::cout << "Reversed: " << s2 << std::endl;
(gdb) n
Reversed: !dlrow ,olleH

更新:

我将代码复制到我的 Mac 上,并尝试在那里进行调试 - 效果非常好:

Breakpoint 1, exscape::string::reverse (this=0x7fff5fbff800) at string.cpp:368
368         string rev;
(gdb) n
378         rev.alloc(this->_length + 1);
(gdb) p rev
$1 = (exscape::string &) @0x7fff5fbff7c0: {
  buf = 0x0, 
  _length = 0, 
  _size = 0
}

虽然 gdb 的那个版本相当古老 - “GNU gdb 6.3.50-20050815(Apple 版本 gdb-1344)”。
我尝试将 Linux gdb 降级到 6.8 和 6.6,但无济于事。 -- 我实际上也尝试过 6.3,也没有用(并且在一个完全不相关的说明中,这些年来选项卡的完成似乎逐渐变得更好 :-)。

最佳答案

我觉得问题可能出在rev是返回值?

我不知道原因,但试试这个代码: 如果你使用 Test *p = &res;

然后在 gdb 中打印 &res 和 p,你会看到这两个地址是不同的,即使你用 -O0 编译它也是如此

#include <iostream>
#include <cstdlib>
#include <cstring>
using namespace std;


struct Test {
 int a;
 int b;
 int c;
 Test() : a(0), b(0), c(0) {}
 Test operator+(const Test &rhs) const;
};

Test Test::operator+(const Test &rhs) const
{
 Test res, nores;
 // cannot print the content of res (uninitialized), but nores is right.
 res.a = a + rhs.a;
 res.b = b + rhs.b;
 res.c = c + rhs.c;
 return res;
}
ostream &operator<<(ostream &out, const Test &a)
{
 out << a.a << ' ' << a.b << ' ' << a.c << endl;
}

int main()
{
 Test p1, p2;
 cout << p1 + p2 << endl;

 return 0;
}

关于c++ - gdb 显示类成员的乱码值,尽管代码有效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1810498/

相关文章:

c++ - 除了制作类的 const 版本之外,还有其他选择吗?

java - 当我们在eclipse Debug模式下修改某个对象时,类加载是如何发生的

c++ - 为什么在Visual Studio Code中将 “C/C++:”插入我的task.json文件的标签中?

GDB检查数据显示格式从连续8字节到4字节

Android NDK memcpy 崩溃,在 libc.so 中带有 proguard 的断回跟踪

c++ - 如何在 Turbo C++ 中将整数作为命令行参数传递

c++ - 当我尝试在非 constexpr 函数中运行 constexpr 函数时会发生什么?

c++ - Fixed_alpha_shape_3() 是否破坏或修改原始三角剖分?

linux - Linux 终端中的双倍间距线

gdb - gdb 中的 <value optimization out> 是什么意思?