c++ - 如何在 gdb 中为 pretty-print 调用构造函数

标签 c++ constructor gdb evaluate

在使用 GDB 进行调试时,我想将一个方便的变量设置为新构造的值。

我正在使用 Qt 框架进行编程,所以我想创建一个 QString,但这与问题无关,因为我想知道如何对任何类执行此操作。

我试过了

(gdb) set $str = 'QString::QString("abc")'
No symbol "QString::QString("abc")" in current context.

(gdb) set $str = QString::QString("abc")
Cannot resolve method QString::QString to any overloaded instance

(gdb) set $str = QString("abc")
A syntax error in expression, near `("abc")'.

然后我尝试使用 set overload-resolution off,结果如下:

set $str = QString::QString("abc")
non-unique member `QString' requires type instantiation

set $str = 'QString::QString(const char*)'("abc")
Too few arguments in function call.

所以我假设需要一个 this 指针:

(gdb) set $str = 'QString::QString(const char*)'(malloc(sizeof(QString)), "abc")
(gdb) p $str
$8 = void

好的,构造函数返回 void,这意味着我必须将 malloc 的返回值保存在某处:

(gdb) set $pointer = malloc(sizeof(QString))
(gdb) p $pointer
$9 = 6304560
(gdb) p/x $pointer
$10 = 0x603330
(gdb) set $str = 'QString::QString(const char*)'($pointer, "abc")
(gdb) p $str
$11 = void
(gdb) p $pointer
$12 = 6304560
(gdb) p *((QString*)$pointer)
$13 = "abc"

好的,现在这按预期工作了,但是我想在 gdb.parse_and_eval() 中将这段代码用于 python pretty-print 。现在这将多次调用 malloc,造成内存泄漏。所以只调用 free() ?现在发生了意想不到的事情:

(gdb) call free($pointer)
$14 = 0
(gdb) p *((QString*)$pointer)
$15 = "abc"

指针似乎仍然有效,这当然可能完全没问题,因为内存没有被重用。但是我不确定这是否可以,因为在分配了更多正好适合一个 QString 的内存块之后,指针值仍然没有被 malloc 重用。

如果我在 pretty-print 中使用它,我是否会造成很大的内存泄漏,在调试 session 期间很可能会调用很多次?是否有更简单的解决方案来创建所需的结果(即使用 Python API)?

同样与此无关,为什么 free(3) 返回值是 0 而它实际上是 void?

最佳答案

我不知道如何释放指针。这似乎是不可能的,但造成的内存泄漏应该是相当小的。但我知道如何消除你描述的效果

The pointer still seems valid, which may of course be perfectly fine, since the memory has not been reused. However I am unsure whether this is okay because after allocating a few more memory blocks which fit exactly one QString the pointer value has still not been reused by malloc.

请参阅此代码,它应该显示如何解决问题(仅在 GNU gdb (GDB) SUSE (7.5.1-2.1.1) 上测试)

(gdb) call malloc(sizeof(std::string))
$1 = (void *) 0x64e4d0
(gdb) call ((std::string*)0x64e4d0)->basic_string()
(gdb) call ((std::string*)0x64e4d0)->assign("Hello World")
$2 = "Hello World"
(gdb) call ((std::string*)0x64e4d0)->'~basic_string'((std::string*)0x64e4d0)
warning: Using non-standard conversion to match method std::string::~basic_string to supplied arguments
(gdb) print ((std::string*)0x64e4d0)
$3 = (std::string *) 0x64e4d0
(gdb) print *((std::string*)0x64e4d0)
$4 = ""
(gdb) call free(0x64e4d0)
(gdb) print *((std::string*)0x64e4d0)
$5 = ""

你的版本不能释放内存的原因是你的释放命令只应该影响直接保留的内存(例如类定义的指针和基本类型),而不是创建的对象(意味着构造函数保留的内存)以及您可能调用的对象的方法)。

需要先调用已创建对象的析构函数,然后释放指针(我的代码中 $2 下面的行)。

因为我代码的最后几行($5)暗示 gdb 的 pretty-print 能够恢复对象的内容,即使对象的内存不再被进程占用。原因可能是打印机几乎可以对每个内存地址执行此操作,并且当没有其他进程向该位置写入内容时(我们在几秒钟前占用了该位置),我们将得到与未调用 free 时相同的结果。

PS:析构函数的格式和警告应该告诉你找到析构函数的正确表达式有点棘手。我没有实际的 QT 项目来尝试使用 QString,但它应该非常接近我所做的。

关于c++ - 如何在 gdb 中为 pretty-print 调用构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7060099/

相关文章:

c++ - 如何在shell脚本中调用c++程序

c++ - 字符串在构造函数中分配但此后变为空白 C++

gdb - 手动生成 elf 核心转储

c++ - cmake 找不到 qt 5.1.1

c++ - Yocto bitbake 与 SDK sysroot 冲突

c++ - 括号与花括号

c++ - 为什么在这种情况下不调用复制构造函数?

c - 如果上一个命令失败,GDB 命令将停止执行

objective-c - 使用 dSYM 文件对故障转储进行符号化时,为什么 GDB 会显示 "no line number info available"?

c++ - boost::spirit::lex 不区分大小写的关键字