2011-02-12 18 views
0

我正在研究这个在Linux中运行的旧C++程序。这是我尝试阅读的最差的代码,并且使用ValGrind运行它会带来大量的内存问题。需要使用Seg错误调试的建议

我想逐个挑选seg故障,但到ValGrind发现该行代码崩溃时,损坏已完成。此代码使用第三方库以及本地库。第三方库是可信的,但不是家乡的。

有没有人有任何建议如何找到导致seg故障的内存损坏?我从来不必在其他人的代码中找到seg故障,特别是没有文档发布的代码。

我今天发现的两件事是编译器设置被更改为NOT自动初始化。值和字大小从32更改为64位。

我在我的智慧结尾试图取得任何进展,任何人都有任何深刻的记忆分析想法?

谢谢

+0

我正在使用DDDB与gdb –

回答

0

GDB是一个很好的建议。您也可以使用ulimit unlimitedman page)让系统在程序崩溃时转储核心文件。

也就是说,这些工具给你的信息在处理内存错误时可能会产生误导。内存损坏可能会导致程序崩溃在一个随机的地方,这与问题的根源很少有关。如果您发现自己正在查看核心转储或GDB输出,并想知道程序如何可能进入该状态,那么很可能就是这样。

在这种情况下,valgrind是你最好的朋友。从内存错误列表的顶部开始,一次一个地修复它们(我的意思是修复一个,然后重新运行,然后修复下一个,等等;这是因为修复一个错误往往会消除许多其他错误),直到他们都走了。那么你的程序要么更稳定,要么你的工具会再次给你提供有用的信息。

+0

我想一次通过一个valgrind错误,但它有一些存在un-init错误的库,我没有访问权限的问题。根据我的理解,该程序就像是一个巨大的双向链表,损坏看起来是在删除链接时完成的,seg故障发生在持久文件写入上。在存储操作发生之前,我似乎无法让valgrind或调试器停止内存损坏。 –

+1

一个有用的技巧是确保所有对象在其析构函数中将所有指针设置为null。这样,如果您的代码尝试使用已释放的对象,则会立即发生段错误,而不是导致最终崩溃的未定义行为。另外,请注意,您可以配置valgrind忽略您无法做任何事情的错误。我不记得我的头脑究竟如何,但文件应该告诉你。 –

+0

我可以试试这个,唯一的缺点就是代码相当大。 –

0

GDB可能是比valgrind更好的选择;当你的应用程序(在gdb下运行)接收到一个SIGSEGV时,gdb将暂停执行并生成一个堆栈跟踪,列出那些调用到那个点的函数,并保留程序内存的状态供你阅读。您需要使用调试信息(gcc中的-g)构建您的应用程序,以使其工作。即使图书馆不能重建,保存程序的内存也许是一个很大的帮助。

0

调试内存损坏的最简单方法是在发生错误后尽早捕获损坏,最好在确切的时间 - 这将允许您查看哪个线程和方法存在错误。

一般腐败是难以捉摸的,因为失败只发生在损害后的一段时间。 Valgrind和其他工具旨在通过采用一些检查来确保缓冲区溢出和其他覆盖被捕获,从而有助于早期捕获损坏。

尝试查看用户指南,或尝试其他工具以查看是否可以强制崩溃或断点接近腐败。

也就是说,在自然的崩溃点使用调试器可以揭示有关损坏的内存的信息,但有时它可能是一个艰难的琐事。像valgrind这样的工具如果不会导致问题消失或造成不可接受的低性能,那么这些工具是无价的。

0

看看你是否可以在内存分配器中启用调试功能。 glibc的malloc实现确实有一些可以以某种方式启用的理智检查。

我曾经有过一个案例(在一个带有简单链式malloc的嵌入式系统上),其中应用程序覆盖了所使用的内存分配器的内部数据结构 - 导致内存分配出现偶发的段错误。

0

感谢大家,不知道是谁给的功劳,但valGrind发现我的问题,似乎代码是在保存操作之前删除需要它们的对象。我花了一点时间,但是得到了valgrind的输出结果,但是对于错误的结果已经死了。