我正在为Windows和Unix编写跨平台的C ++程序。在窗口方面,代码将编译并执行没有问题。在Unix方面,它将编译,但是当我尝试运行它时,出现了分段错误。我最初的预感是指针存在问题。
有什么好的方法来查找和修复分段错误?
我正在为Windows和Unix编写跨平台的C ++程序。在窗口方面,代码将编译并执行没有问题。在Unix方面,它将编译,但是当我尝试运行它时,出现了分段错误。我最初的预感是指针存在问题。
有什么好的方法来查找和修复分段错误?
Answers:
使用编译应用程序-g
,然后在二进制文件中就有调试符号。
使用gdb
打开GDB控制台。
file
在控制台中使用并传递您的应用程序的二进制文件。
使用run
并传入您的应用程序需要启动的任何参数。
采取措施导致细分错误。
bt
在gdb
控制台中键入以获取Segmentation Fault的堆栈跟踪。
cmake -DCMAKE_BUILD_TYPE=Debug
。
在出现问题之前,请尝试尽可能避免它:
使用适当的工具进行调试。在Unix上:
-fsanitize=address
标志一起使用。最后,我将推荐平常的事情。您的程序可读性,可维护性,清晰性和整洁性越强,调试起来就越容易。
在Unix上,您可以valgrind
用来查找问题。它是免费且强大的。如果愿意,可以重载new
anddelete
运算符以设置一个配置,在该配置中0xDEADBEEF
,每个新对象的前后都有1个字节。然后跟踪每次迭代发生的情况。这可能无法捕获所有内容(您甚至不能保证碰到那些字节),但是过去在Windows平台上它对我有用。
new
和delete
可超实用,采用的-fsanitize=address
是一个更好的选择,因为编译器将在运行时检测编译的问题,并会自动转储内存,屏幕,这使得调试比较容易的方式。
是的,指针有问题。您很有可能正在使用未正确初始化的内存,但也有可能使用双重释放或诸如此类的方法来弄乱内存管理。
为了避免将未初始化的指针作为局部变量,请尝试尽可能晚地声明它们,最好是(这并不总是可能的)在可以使用有意义的值对其进行初始化时声明它们。通过检查代码,使自己确信在使用之前它们将具有价值。如果您对此感到困难,请将其初始化为空指针常量(通常写为NULL
或0
)并检查它们。
为了避免将未初始化的指针作为成员值,请确保在构造函数中正确初始化了它们,并在副本构造函数和赋值运算符中对其进行了正确处理。init
尽管可以进行其他初始化,但不要依赖于函数来进行内存管理。
如果您的类不需要复制构造函数或赋值运算符,则可以将它们声明为私有成员函数,而不用定义它们。如果显式或隐式使用它们,将导致编译器错误。
适用时使用智能指针。这里的最大优点是,如果您坚持使用它们并始终如一地使用它们,则可以完全避免书写,delete
并且不会重复删除任何内容。
尽可能使用C ++字符串和容器类,而不是C样式的字符串和数组。考虑使用.at(i)
而不是[i]
,因为这将强制进行边界检查。查看是否可以将您的编译器或库设置为[i]
至少在调试模式下检查的界限。分段错误可能是由缓冲区溢出所引起的,缓冲区溢出将垃圾写入了非常好的指针。
这样做会大大降低分段错误和其他内存问题的可能性。他们无疑将无法修复所有问题,这就是为什么您不时出现问题时应立即使用valgrind的原因,而在出现问题时应使用valgrind和gdb的原因。
g
在的上下文中进行编译意味着什么CMake
?