gdb:不在上下文中的结构的大小?

Posted

技术标签:

【中文标题】gdb:不在上下文中的结构的大小?【英文标题】:gdb: size of a struct that isn't in context? 【发布时间】:2015-03-11 09:18:08 【问题描述】:

有时我需要知道不在范围内的结构的大小(甚至不在堆栈上,即frame 相关命令无济于事)。例如。它发生在调试客户端+服务器通信时,当重新启动应用程序以在结构上下文中的某个地方中断以查找大小的目的时,会感到不舒服且耗时。

如何在不考虑当前上下文的情况下找到在标头中定义的 struct 的大小?

【问题讨论】:

像Use gdb to call a printDebug method 这样的东西怎么样:编写一个打印出结构大小的函数,重建您的应用程序并在需要有关大小信息的调试期间调用该函数? @AntoJurković 我宁愿手动计算。我以前无法为特定结构编写方法,因为我不知道哪一个对我来说很有趣。当然,我可以为 app 中的所有现有结构编写函数,但我认为这不值得;同样根据 Merphi 的规则,我很可能对这些功能不感兴趣,以备将来调试。 您能否举一个程序示例,其中在#included 文件中定义了结构但gdb 无法访问它?它们应该几乎总是导致结构出现在全局级符号表中,除非是显式声明 static 的结构。 【参考方案1】:

对于 C,gdb 的“表达式语言”只是普通的 C 表达式,带有一些方便的调试扩展。这对于 C++ 来说不太正确,主要是因为 C++ 更难解析,所以表达式语言往往是 C++ 的子集加上一些 gdb 扩展。

所以,简短的回答是您只需输入:

(gdb) print sizeof(mystruct)

但是,有一些警告。

首先,gdb 的当前语言很重要。您可以通过show language 找到它。对于 struct 类型,在 C++ 中有一个自动 typedef,但在 C 中没有。因此,如果您使用的是auto 语言(并且您通常应该这样做),并且在 C 框架中停止,您将需要使用关键字:

(gdb) print sizeof(struct mystruct)

现在,这仍然可能行不通。此时通常的原因是该结构未在您的程序中使用,因此不会显示在调试信息中。即使您认为调试信息应该可用,也可以优化调试信息,因为它取决于编译器。例如,我认为如果 struct 仅用于 sizeof 表达式(并且从未定义过该类型的变量),那么我认为(很难确定)GCC 不会为它发出 DWARF。

您可以使用readelfdwgrep 来检查该类型是否可用,例如:

$ readelf -wi myexecutableorlibrary | grep mystruct

(虽然在现实生活中我通常使用less,然后仔细检查 DWARF DIE。您需要了解一点 DWARF 才能理解这一点。)

有时在 gdb 中使用“文件名”扩展名来准确指定您所指的实体很方便。喜欢:

(gdb) print 'myfile.c'::variable

不确定这是否适用于类型,无论如何,它们通常不需要。

【讨论】:

我认为它很迂腐,但还有一个警告是 C 不一定遵循一个定义规则,因此特定上下文之外的类型的 sizeof 可能会遇到多种类型,但希望这种情况很少见 是的,没错。而“::”扩展对此很有用。假设它有效——我认为它有效,但我最近没有尝试过,而且我的记忆...... @MarkPlotnick 在评论中指出这看起来像是一个错误。他们评论说,头文件中的所有结构大部分都应该以全局命名空间结束,即我应该能够访问它,而不管我的代码执行在我停止它的那一刻已经走了多远。然后我仔细检查了代码,发现实际上是这样,错误只是因为结构位于单独的命名空间中。由于这是一个错误,这个答案也可以,所以我检查一下。 @Hi-Angel 在我对您的问题的评论中,我并不是要暗示犯了任何错误。我只是想看一个 gdb 找不到在头文件中声明的(静态除外)结构的示例,以便我可以了解它发生的原因。 在 C 中,头文件中包含不完整的 struct 并不完全不常见,例如“struct whatever;”,然后在两个不同的源文件中对其进行不同的定义。这不是 C 中的错误,只是有时令人困惑,因为在 C 中没有 ODR(并且因为类型没有链接)。 gdb 扩展可以让你处理这个问题。【参考方案2】:

在 C/C++ 中,您有 sizeof 函数,它可以为您提供任何类型(包括 struct)或变量的大小。

我不确定你是否可以在调试时应用它,但你可以简单地让一个具有相同标题(类型定义)的测试程序告诉你你的类型的大小是多少。

【讨论】:

不,我需要知道它不是在 C 代码中,而是在调试已编译 C 代码的 gdb 中。编写具有相同标头的测试应用程序将花费更多时间,而不仅仅是手动计算。 这样的话,和gdb差不多,看看这个:***.com/questions/5645027/… 是的,这个关闭了。不幸的是,命令print sizeof(mystruct) 会导致错误mystruct is not in current context,除非它是。 变量是属于上下文的东西。当我需要打印变量时,如果变量在上下文中当然可以。但就我而言,我没有变量,只是一个大小只有 gdb 知道的抽象结构。 仅供参考 print sizeof(mystruct) 可用于变量和“抽象结构”,但结构必须在上下文中。 IE。 gdb 执行停止的地方应该在源代码中包含带有该结构的标头。在我的情况下,我经常在这些文件之外的某个地方,这些文件包括我感兴趣的 struct。也就是说,我不在上下文中。

以上是关于gdb:不在上下文中的结构的大小?的主要内容,如果未能解决你的问题,请参考以下文章

每次都让 GDB 打印上下文

跟踪所有变量以执行gdb中的函数

如何获取不在上下文中的linq-query实体?

SwiftUI:滚动视图中的顶部锚定可调整大小视图

多线程程序中的分段错误和 gdb 回溯信息不完整

[QNX Hypervisor 2.2用户手册]7.1 使用GNU调试器(GDB)