首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在gdb中为漂亮的打印机调用构造函数

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

Stack Overflow用户
提问于 2011-08-15 06:19:57
回答 2查看 2.9K关注 0票数 8

在使用GDB进行调试时,我希望将便利变量设置为新构造的值。

我使用Qt框架编程,所以我想创建一个QString,但这与问题无关,因为我想知道如何使用任何类来做到这一点。

我试过了

代码语言:javascript
复制
(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,结果如下:

代码语言:javascript
复制
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指针:

代码语言:javascript
复制
(gdb) set $str = 'QString::QString(const char*)'(malloc(sizeof(QString)), "abc")
(gdb) p $str
$8 = void

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

代码语言:javascript
复制
(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()就行了?现在一些意想不到的事情发生了:

代码语言:javascript
复制
(gdb) call free($pointer)
$14 = 0
(gdb) p *((QString*)$pointer)
$15 = "abc"

指针看起来仍然有效,这当然可能是完全正常的,因为内存还没有被重用。然而,我不确定这是否可以,因为在分配了几个正好适合一个QString的内存块之后,指针值仍然没有被malloc重用。

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

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-03-31 18:21:34

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

指针看起来仍然有效,这当然是非常好的,因为内存还没有被重用。然而,我不确定这是否可以,因为在分配了几个正好适合一个QString的内存块之后,指针值仍然没有被malloc重用。

请看这段代码,它应该展示如何解决问题(仅在GNU gdb (GDB) SUSE (7.5.1-2.1.1)上测试)

代码语言:javascript
复制
(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项目来尝试与QString,但它应该是相当接近,我已经做了。

票数 1
EN

Stack Overflow用户

发布于 2011-08-20 19:46:58

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

代码语言:javascript
复制
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'
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7060099

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档