2010-04-30 86 views
4

我有一个缓冲区溢出,我绝对看不出来(在C中)。首先,大概只有10%的时间发生。每次从数据库中提取的数据在执行之间似乎没有太大的差异......至少在我看来不会发现任何可识别的模式。从Visual Studio确切的消息是这样的:需要缓冲区溢出的帮助

缓冲区溢出发生在 hub.exe已损坏的 程序的内部状态。按 中断调试程序或继续 终止程序。

有关更多详细信息,请参阅帮助主题 '如何调试缓冲区溢出问题'。

如果我调试,我发现它在__report_gsfailure(),我敢肯定是从编译器/ GS标志,也意味着这是堆栈溢出,而不是堆破碎。我也可以看到它在离开时抛弃它的功能,但是我看不到会导致这种行为的任何东西,这个功能也存在了很长时间(10年以上,虽然稍作修改)据我所知,这从来没有发生过。

我会发布函数的代码,但它很长,并引用了很多专有函数/变量/等。

我基本上只是寻找一些我应该寻找的想法,我没有或者可能有些工具可以帮助。不幸的是,我发现几乎所有的工具都只能帮助调试堆上的溢出,除非我错了,这是堆栈中的事情。提前致谢。

回答

3

您可以尝试在缓冲区的任一端放置一些局部变量,甚至将缓冲区本身放在稍稍扩展的缓冲区中,如果这些值不是您认为应该是的那么就触发一个断点。显然,使用数据中不太可能的模式将是一个好主意。

+0

我加入了一些本地变量缓冲区,希望能够获得一些价值,并且这个问题在25次左右的尝试中都没有被重现(这比以前我所做的要多2-3倍)。这就像我添加的缓冲区填充了一切,足以让任何事情都没有崩溃。即使在我调试它们的时候,缓冲区在每次从函数返回之前都会保持我期望它们的确切值。 – Morinar 2010-04-30 21:42:00

+0

如果你只是扩展你的缓冲区,并且在它的末尾写入一些已知的值,那该怎么办? – 2010-04-30 21:44:59

+0

你说如果我知道我正在覆盖哪个缓冲区。如果不明确,我完全不知道。如果我知道哪个缓冲区超时,我只会设置一个硬件断点并获胜。 – Morinar 2010-04-30 22:26:26

3

虽然它不会帮助你在Windows中,Valgrind是迄今为止检测不良内存行为的最佳工具。

如果您正在调试堆栈,您需要使用低级工具 - 在任何潜在的嫌疑人周围放置一个金丝雀到堆栈框架(可能是一个填充类似0xA5的缓冲区)。在调试器中运行该程序,并查看哪些canaries不再是正确的大小并包含正确的内容。你会吞噬一大堆这样做,但它可以帮助你确切地发现正在发生的事情。

+0

是的,我以前用过它。虽然我们的服务器代码确实在各种Unix(Solaris/HP/AIX)上运行,但它看起来并不像Valgrind那样受支持,所以不幸的是,它并不能帮助我。 – Morinar 2010-04-30 18:48:47

0

将其包装在异常处理程序中,并在发生时转储出有用的信息。

0

这个程序是否递归?如果是这样,我在那里检查以确保您没有无限递归错误。如果你不能手动看到它,有时你可以通过频繁停顿和观察堆栈来在调试器中捕获它。

+0

没有。没有递归。 – Morinar 2010-04-30 21:09:01

1

我过去做过的一件事是帮助缩小这样一个神秘错误,就是创建一个名为checkpoint的全局可见性变量。在罪魁祸首里面,我设置了checkpoint = 0;作为第一行。然后,我在函数调用或内存操作之前和之后添加了++checkpoint;语句,我甚至可以远程怀疑这些语句可能会导致超出内存的引用(加上其他代码,这样我至少每10次有一个检查点线左右)。当程序崩溃时,checkpoint的值将缩小您需要关注的几行代码的范围。这可能有点矫枉过正,我在嵌入式系统上做这种事情(不能使用像valgrind这样的工具),但它应该仍然有用。

+0

好主意!接下来会尝试。 – Morinar 2010-04-30 21:05:29

+0

我有一个几乎所有其他的线......当它崩溃的时候它的价值就是它应该是的。 :- – Morinar 2010-04-30 21:40:21

+0

我不明白你的意思。如果在程序崩溃时检查点是6(例如),那么你的问题发生在第六个和第七个“++检查点”语句之间。如果你能够在崩溃后读取这个值,它应该找出问题的根源。 – bta 2010-04-30 21:55:35