【问题标题】:Good way to debug stack value corruption调试堆栈值损坏的好方法
【发布时间】:2014-01-28 07:01:33
【问题描述】:

什么是调试堆栈值损坏的好方法。在我的一个程序中,有时 this 指针的地址会在方法返回后更改,该方法对文件描述符进行关闭。我调试程序几个小时,但我找不到问题。

有什么好的方法可以找出 this 指针的地址发生了什么变化?当我在 this 指针上手动添加手表时,不会发生错误。当我尽可能地剥离我的代码时,错误仍然存​​在。我尝试了 Valgrind,但它没有发现任何早期的堆栈损坏。

我设法检测到错误何时发生,我以 64 位模式编译了代码。这个地址从 0xxxxxxx 变成了 0x1000000xxxxxxx。我在发生错误的方法中检查了这个地址,当地址发生变化时我发现了这个地址(参见第一段)。

有没有其他方法可以找出这个问题的原因?

【问题讨论】:

  • 添加-fstack-protector-fstack-protector-all 编译器选项?
  • 当变量超出范围时会自动删除手表。将程序运行到已知的好点。找到损坏的变量的地址,并在该地址的内容上添加一个监视,而不是变量,即如果 variable 的地址是 0x12345678(不是 0xxxxxxxxx 的内容根据您的问题)然后在 *(void **)0x12345678 上设置硬件写入手表并继续您的程序。
  • 栈上的this指针被改变了。程序继续执行,但是当我调用类变量时(this + variable position)将无效。仅当我快速创建和销毁对象时才会出现问题(该对象包含文件描述符并在销毁时将其关闭)。有什么办法可以自动添加手表软件吗?这会让事情变得容易得多。

标签: c++ linux debugging gcc stack-corruption


【解决方案1】:

您可能想试一试address-sanitizer。是available in gcc 4.8:

AddressSanitizer 是一种快速内存错误检测器,已添加并 可以通过-fsanitize=address 启用。内存访问指令将 检测堆、堆栈和全局缓冲区溢出 以及释放后使用的错误。要获得更好的堆栈跟踪,请使用 -fno-omit-frame-pointer。 AddressSanitizer 在 IA-32/x86-64/x32/PowerPC/PowerPC64 GNU/Linux 和 x86-64 Darwin 上可用。

在 GCC(但显然不是 clang)中,您需要在 both 编译器标志 链接器标志中指定 -fsanitize=address,如 this related answer 中所述。

【讨论】:

  • 那个工具发现了一个堆栈缓冲区溢出,但是堆栈跟踪不是很方便(我使用了“-fno-omit-frame-pointer”选项,你可以在这里找到堆栈跟踪:pastebin.com/b81eUnZq)。该工具输出:“project+0x47744c”。我怎样才能到达源代码中的那个位置?我使用 Eclipse 作为 IDE。
  • 请尝试使用-ggdb3 进行编译。这通常会提供很好的调用堆栈。
  • 再想一想,您可能想要完全禁用优化 (-O0) 并添加 -ggdb3-fno-omit-frame-pointer(我知道您添加了后者)。希望这会有所帮助。
  • 问题解决了。非常感谢你!这个问题我花了8个多小时调试。
  • @user35774 我很高兴它有帮助!哪个标志有帮助? -ggdb3-O0?
猜你喜欢
  • 1970-01-01
  • 2017-06-07
  • 1970-01-01
  • 2012-04-06
  • 2015-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-11
相关资源
最近更新 更多