【问题标题】:c heap memory layoutc堆内存布局
【发布时间】:2018-02-06 08:46:42
【问题描述】:

我正在开发一个使用结构链表的相当复杂的 c 程序。在我的一个 .c 文件 (queue_head) 的顶部声明了一个全局变量。这个变量现在被神秘地覆盖了,这会导致段错误。

有没有办法找出我的变量在内存中的布局。我对原因的最佳猜测是,某些内容正在写入超出其内存的末尾并覆盖 queue_head 内存位置。

为了测试我在源文件中颠倒了 queue_head 和 queue_tail 的位置,下次我运行程序时,queue_tail 已损坏,但 queue_head 很好。

当然它可能是一个错误的指针,但我相信它背后的一些东西在内存中被写入超过它的内存分配。

有没有办法查看 c 如何映射出没有反汇编的变量?

【问题讨论】:

标签: c memory layout fault


【解决方案1】:

变量在文件中一般是按照出现的顺序排列的,但是如果程序有多个文件,那就更难预测了。您可以打印他们的地址以查找可能的罪犯:

printf("%p %p\n", &queue_head, &fishy_var);

但是找到前一个变量有什么好处呢?很可能会发生损坏的代码不直接引用它。

更好的方法是使用调试器。例如,如果您可以在 gdb 中运行程序,那么您可以使用观察点在内存损坏的位置中断:watch queue_head。之后这个程序会在每次 queue_head 的值改变时中断,包括合法使用。为了隔离合法使用,在 queue_head 之前添加虚拟指针变量并观察它:

void *fishy_var;
queue *queue_head;

然后在 gdb 中:

break main
run
watch fishy_var
continue

这应该会导致错误的代码。

请注意,您最好将我之前在 main 开头显示的 printf 设置为 1. 确保变量在内存中是连续的 2. 确保编译器不会优化掉未使用的 fishy_var。

【讨论】:

  • 是的,我明白你在说什么。昨晚我又搞砸了一些,并在文件中的同一位置放置了更多变量。我能够将所有有问题的覆盖写入我添加的一些虚假整数中,然后可以读取它们。那里有字符串数据,有助于隔离代码。直到稍后才能再次处理它,但我开始知道错误在哪里。
  • 再次感谢。我将此作为选定的答案,因为它导致了解决方案。我以前没用过gdb。这是一本很棒的入门书。对于其他来这里的人,我将添加一些我需要使它工作的点。将 CFLAGS += -g 添加到 Makefile,以便可执行文件中包含调试信息。我的可执行文件需要 args 来重现问题,为此您运行 gdb --args ... 最后,由于我的程序每次都在 strcpy 中间中断,请输入 bt 或 backtrace 到在我的可执行文件中找到要修复的行。这列出了带有确切行的调用堆栈。
【解决方案2】:

从大多数编译器(或更可能的链接器)中,您可以生成一个 .map 文件,该文件将列出所有全局变量和函数。

您没有提及您使用的编译器,但对于 gcc,this 会回答您的问题。

基本上,将其添加到您的 gcc 行:

 -Xlinker -Map=output.map 

【讨论】:

  • 我相信,OP 正在寻求一种在运行时获取变量内存布局的方法。
  • 其实,这就是我要找的。我记得我早期 C 编程时的地图文件之类的东西。我现在没有得到它们,但不知道它的选项。我正在使用 gcc。我赞成这两个答案,因为两者都适用于该问题。这个最好回答了我特别问的问题。
猜你喜欢
  • 2014-12-05
  • 2016-06-23
  • 1970-01-01
  • 2015-09-22
  • 2016-09-11
  • 2014-03-07
  • 2010-12-10
  • 2012-07-09
  • 2019-05-02
相关资源
最近更新 更多