如何在 gdb 中调用漂亮打印机的构造函数

发布于 2024-11-29 10:24:39 字数 1675 浏览 4 评论 0原文

当使用 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 override-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 漂亮的打印机。现在这将多次调用 malloc,从而造成内存泄漏。那么只要调用 free() 就可以了吗?现在发生了一些意想不到的事情:

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

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

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

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

When debugging with GDB I would like to set a convenience variable to a newly constructed value.

I am programming using the Qt framework, so i would like to create a QString, but this is irrelevant to the question, since I would like to know how to do this with any class.

I tried

(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")'.

then I tried using set overload-resolution off, resulting in the following:

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.

So I assumed a this pointer is needed:

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

Okay, constructors return void, that means I have to save the return value of malloc somewhere:

(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"

Okay, now this works as expected, however I want to use this code in gdb.parse_and_eval() for a python pretty printer. Now this will call malloc lots of times, creating a memory leak. So just call free()? Now something unexpected happens:

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

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.

Am I creating a big memory-leak if I use this in a pretty-printer, which may well be called lots of times during a debug session? Is there any easier solution of creating the desired result (i.e. using the Python API)?

Also unrelated to this, why is free(3) giving me a return value of 0 while it is actually void?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

青衫儰鉨ミ守葔 2024-12-06 10:24:40

你想做什么?如果您想使用 gdb 漂亮地打印 QString,请使用 gdb 的 Python 漂亮打印机 API。请参阅http://sourceware.org/gdb/onlinedocs/gdb/Pretty-Printing。 html 了解详细信息。您可以使用如下所示的 Python 打印机类:

class QStringPrinter:
    def __init__(self, val):
        self.val = val

    def to_string(self):
        if self.val['d'] == self.val['shared_null'].address:
            return 0

        dataptr = self.val['d']['data'].cast(gdb.lookup_type('char').pointer())
        size = self.val['d']['size']

        if sys.byteorder == 'little':
            enc = 'utf_16_le'
        else:
            enc = 'utf_16_be'
        return dataptr.string(enc, 'ignore', size * 2)

    def display_hint(self):
        return 'string'

What are you trying to do? If you want to pretty-print a QString with gdb, use gdb's Python pretty printer API. See http://sourceware.org/gdb/onlinedocs/gdb/Pretty-Printing.html for details. You can use a Python printer class like the following:

class QStringPrinter:
    def __init__(self, val):
        self.val = val

    def to_string(self):
        if self.val['d'] == self.val['shared_null'].address:
            return 0

        dataptr = self.val['d']['data'].cast(gdb.lookup_type('char').pointer())
        size = self.val['d']['size']

        if sys.byteorder == 'little':
            enc = 'utf_16_le'
        else:
            enc = 'utf_16_be'
        return dataptr.string(enc, 'ignore', size * 2)

    def display_hint(self):
        return 'string'
恍梦境° 2024-12-06 10:24:39

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

指针似乎仍然有效,这当然可能完全没问题,因为内存尚未被重用。但是我不确定这是否可以,因为在分配了更多适合一个 QString 的内存块后,指针值仍然没有被 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 = ""

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

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

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

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

I do not know how to free the pointer. It seems to be impossible, but the memory leak created should be quite small. But I know how to remove the effect you described as

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.

See this code that should show how one could solve the problem (tested only on 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 = ""

The reason why your version could not free the memory is that your free command only should affect the direct reserved memory (e.g. the pointers and basic types defined by the class), not the created object (meaning the memory reserved by the constructor and the methods of the object you might call).

One needs to call first the destructor of the created object and then free the pointer (line below $2 in my code).

As the last lines ($5) of my code imply the pretty printer of the gdb is able to restore the content of the object even when the memory of the object is not longer occupied by the process. The reason might be that the printer could do this with nearly every memory address and when no other process had written something to this place (that we had occupied a few seconds before) we would get the same results as when free was not called.

PS: The format of the destructor and the warning should show you that it is a little bit tricky to find the right expression of the destructor. I have no actual QT-Project to try this with QString, but it should be quite near that I have done.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文