【问题标题】:How is Valgrind able to access line number of memory allocation in compiled C program, how I can I do the same?Valgrind 如何能够访问已编译 C 程序中内存分配的行号,我该怎么做?
【发布时间】:2020-01-16 13:09:35
【问题描述】:

当我运行一个简单的 Valgrind 命令时,例如...

valgrind --leak-check=yes ./my_program

... Valgrind 产生的错误输出显示了在源代码中分配内存的位置以及释放的位置。 Valgrind 是如何做到这一点的?在程序的代码中,我自己怎么能做到这一点?如果有帮助,我的 GCC makefile 中为编译定义的 CFLAGS 参数是:

CFLAGS=-c -Wall -Wextra -Wno-unused-parameter -Wno-unused-variable -g -Og -std=c11 -pedantic

【问题讨论】:

  • 提示:-g 用于在二进制文件中添加调试信息,可用于显示此类信息。
  • 您可以查看 libbfd,例如gnu.org/software/binutils

标签: c compilation valgrind diagnostics


【解决方案1】:

Valgrind 产生的错误输出显示了在源代码中分配内存的位置以及释放的位置。 Valgrind 是如何做到这一点的?

当您使用 valgrind 时,您不会直接启动您的程序。相反,valgrind 在一个环境中并通过允许它首先进行监控的方式来做到这一点。这包括但不限于用它自己的分配函数代替标准库的正常实现。正是这些替代分配函数使 Valgrind 能够跟踪 二进制文件中发生分配和释放的位置。

当您使用-g 选项编译时,将源代码行号与已编译二进制文件中的特定指令相关联所需的信息是二进制文件中包含的调试信息的一部分。如果您省略 -g,您会发现 Valgrind 的输出对于错误位置的信息较少。

我自己如何在程序代码中做到这一点?

您也可以提供自己的malloc。和free 函数。您可以在整个程序中使用它们而不是标准库的版本,尽管细节可能部分取决于您的 C 实现。正确执行此操作并非易事,细节取决于系统。

这些函数可以识别调用它们的点的方法更加重要和系统相关。 C 语言没有定义任何类型的内省功能,例如这需要,因此您需要自己提供。

标准 C 也没有定义程序可以从自己的二进制文件访问调试信息的任何方式,甚至没有任何可靠的方式来定位自己的二进制文件,也没有就此而言,“调试信息”。 Valgrind 在这方面比程序本身有明显的优势:自从 valgrind 启动程序以来,valgrind 就可以知道它正在启动什么二进制文件。

总体而言,答案是,如果您必须首先提出问题,那么您可能根本没有能力去做您提出的问题。相反,您应该寻找一个与您想要的足够接近的现有工具(可能是 valgrind 本身),或者更改您的要求。特别是,您应该考虑@ryyker 的答案中描述的基于预处理器的机制是否提供了一种足够接近您的想法的方法。

【讨论】:

    【解决方案2】:

    ...在编译的C程序中访问内存分配的行号,我该怎么做?

    预定义的宏,例如__FILE____FUNCTION____LINE__,可以在 C 源代码中用于输出有关发生某事的位置的信息。宏的数量和种类在某种程度上取决于环境。 __FUNCTION__ 例如是一个扩展,不在标准指定的预定义宏中,正如 cmets 中指出的那样。 You can read about GCC macro usage and extensions here。 (有关使用的其他提示,请参阅上面的链接。)

    在本例中,这些宏用于显示事件发生在哪个文件、函数和哪一行:

    char buf[100];
    sprintf(buf, "%p (%s() %s() line# %d)\n", malloc(10), __FILE__, __FUNCTION__, __LINE__);
    printf(buf);//(Or more likely usage, write to a log file)
    

    请注意,此示例没有错误检查/处理,例如检查 malloc() 的返回值,这始终是个好主意。

    【讨论】:

    • 要添加,像 valgrind 这样的框架会为现有的库函数添加钩子,并使用这些宏等来插入这些信息,然后在调试期间使用它们。
    • 我对 Valgrind 不太有信心(从没看过源代码),但这通常是策略。我为我的一个项目做了这个。如果您确定 valgrinds 会这样做,请随时添加,否则,请在评论中提示。
    猜你喜欢
    • 2020-09-27
    • 1970-01-01
    • 2011-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-28
    • 1970-01-01
    • 2023-03-13
    相关资源
    最近更新 更多