我正在为Windows和Unix编写一个跨平台的C ++程序。在Window端,代码将编译并执行没有问题。在Unix方面,它会编译然而当我尝试运行它时,我得到一个分段错误。我最初的预感是指针存在问题。
找到并修复细分错误的好方法是什么?
答案 0 :(得分:96)
使用-g
编译您的应用程序,然后您将在二进制文件中包含调试符号。
使用gdb
打开gdb控制台。
使用file
并将其应用程序的二进制文件传递给控制台。
使用run
并传入您的应用程序需要启动的任何参数。
做一些事情导致分段错误。
在bt
控制台中键入gdb
以获取分段错误的堆栈跟踪。
答案 1 :(得分:29)
有时崩溃本身并不是问题的真正原因 - 也许记忆在早些时候被粉碎,但腐败显示需要一段时间。查看valgrind,它有很多指针问题检查(包括数组边界检查)。它会告诉你启动的问题,而不仅仅是发生崩溃的行。
答案 2 :(得分:16)
在问题出现之前,尽量避免使用它:
使用适当的工具进行调试。在Unix上:
最后我会推荐通常的事情。程序的可读性,可维护性,清晰性和整洁程度越高,调试就越容易。
答案 3 :(得分:3)
在Unix上,你可以使用valgrind来查找问题。它是免费且强大的。如果你想自己做,你可以重载new和delete运算符来设置一个配置,你在每个新对象之前和之后有一个带0xDEADBEEF
的字节。然后跟踪每次迭代发生的事情。这可能无法捕获所有内容(您无法保证甚至触及这些字节)但过去它在Windows平台上对我有用。
答案 4 :(得分:2)
是的,指针存在问题。很可能你正在使用一个没有正确初始化的,但也有可能你用双倍释放或其他一些东西来搞乱你的内存管理。
为了避免未初始化的指针作为局部变量,尝试尽可能晚地声明它们,当它们可以用有意义的值初始化时,最好(并且这并不总是可行)。通过检查代码,说服自己在使用之前会有一个价值。如果您遇到困难,请将它们初始化为空指针常量(通常写为NULL
或0
)并检查它们。
要避免未初始化的指针作为成员值,请确保它们在构造函数中正确初始化,并在复制构造函数和赋值运算符中正确处理。尽管您可以进行其他初始化,但不要依赖init
函数进行内存管理。
如果您的类不需要复制构造函数或赋值运算符,则可以将它们声明为私有成员函数,而不是定义它们。如果明确或隐式使用它们,将导致编译器错误。
适用时使用智能指针。这里的最大优点是,如果你坚持使用它们并且始终如一地使用它们,你就可以完全避免写delete
而且不会删除任何内容。
尽可能使用C ++字符串和容器类,而不是C风格的字符串和数组。考虑使用.at(i)
而不是[i]
,因为这会强制进行边界检查。查看您的编译器或库是否可以设置为检查[i]
上的边界,至少在调试模式下是这样。分段错误可能是由缓冲区溢出引起的,它会在完美的指针上写入垃圾。
做这些事情将大大降低分段错误和其他内存问题的可能性。他们无疑无法解决所有问题,这就是为什么你应该在你没有问题时偶尔使用valgrind,以及在你做的时候使用valgrind和gdb。
答案 5 :(得分:0)
我不知道有任何方法可用于修复此类问题。我不认为有可能想出一个问题,因为你的程序的行为是未定义的(我不知道SEGFAULT不是由某种UB引起的任何情况)
在问题出现之前,有各种各样的“方法论”可以避免这个问题。一个重要的是RAII。
除此之外,你只需要投入最好的精神能量。