修复 C++ 中的分段错误
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3718998/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Fixing Segmentation faults in C++
提问by Elpezmuerto
I am writing a cross-platform C++ program for Windows and Unix. On the Window side, the code will compile and execute no problem. On the Unix side, it will compile however when I try to run it, I get a segmentation fault. My initial hunch is that there is a problem with pointers.
我正在为 Windows 和 Unix 编写一个跨平台的 C++ 程序。在 Window 端,代码将编译和执行没有问题。在 Unix 端,它会编译,但是当我尝试运行它时,出现分段错误。我最初的预感是指针有问题。
What are good methodologies to find and fix segmentation fault errors?
查找和修复分段错误错误的好方法是什么?
回答by Svisstack
Compile your application with
-g
, then you'll have debug symbols in the binary file.Use
gdb
to open the gdb console.Use
file
and pass it your application's binary file in the console.Use
run
and pass in any arguments your application needs to start.Do something to cause a Segmentation Fault.
Type
bt
in thegdb
console to get a stack trace of the Segmentation Fault.
使用 编译您的应用程序
-g
,然后您将在二进制文件中获得调试符号。使用
gdb
打开GDB控制台。file
在控制台中使用并传递应用程序的二进制文件。使用
run
并传递应用程序启动所需的任何参数。做一些导致Segmentation Fault 的事情。
bt
在gdb
控制台中键入以获取Segmentation Fault的堆栈跟踪。
回答by paleozogt
Sometimes the crash itself isn't the real cause of the problem-- perhaps the memory got smashed at an earlier point but it took a while for the corruption to show itself. Check out valgrind, which has lots of checks for pointer problems (including array bounds checking). It'll tell you where the problem starts, not just the line where the crash occurs.
有时,崩溃本身并不是问题的真正原因——也许内存在较早的时候就被破坏了,但是损坏需要一段时间才能显现出来。查看valgrind,它对指针问题进行了大量检查(包括数组边界检查)。它会告诉您问题从哪里开始,而不仅仅是发生崩溃的那一行。
回答by log0
Before the problem arises, try to avoid it as much as possible:
在问题出现之前,尽量避免:
- Compile and run your code as often as you can. It will be easier to locate the faulty part.
- Try to encapsulate low-level / error prone routines so that you rarely have to work directly with memory (pay attention to the modelization of your program)
- Maintain a test-suite. Having an overview of what is currently working, what is no more working etc, will help you to figure out where the problem is (Boost testis a possible solution, I don't use it myself but the documentation can help to understand what kind of information must be displayed).
- 尽可能多地编译和运行你的代码。定位故障部分会更容易。
- 尝试封装低级/容易出错的例程,以便您很少需要直接使用内存(注意程序的建模)
- 维护一个测试套件。概述当前正在工作的内容,不再工作的内容等,将帮助您找出问题所在(Boost 测试是一个可能的解决方案,我自己不使用它,但文档可以帮助您了解是什么类型的必须显示信息)。
Use appropriate tools for debugging. On Unix:
使用适当的工具进行调试。在 Unix 上:
- GDBcan tell you where you program crash and will let you see in what context.
- Valgrindwill help you to detect many memory-related errors.
With GCC you can also use mudflapWith GCC and Clang you can use Address/Memory Sanitizer. It can detect some errors that Valgrind doesn't and the performance loss is lighter.
- GDB可以告诉您程序崩溃的位置,并让您查看在什么上下文中。
- Valgrind将帮助您检测许多与内存相关的错误。
使用 GCC,您还可以使用mudflap使用 GCC 和 Clang,您可以使用Address/Memory Sanitizer。它可以检测到一些 Valgrind 没有的错误并且性能损失更轻。
Finally I would recommend the usual things. The more your program is readable, maintainable, clear and neat, the easiest it will be to debug.
最后我会推荐通常的东西。您的程序可读性、可维护性、清晰性和整洁性越强,调试就越容易。
回答by wheaties
On Unix you can use valgrind to find issues. It's free and powerful. If you'd rather do it yourself you can overload the new and delete operators to set up a configuration where you have 1 byte with 0xDEADBEEF
before and after each new object. Then track what happens at each iteration. This can fail to catch everything (you aren't guaranteed to even touch those bytes) but it has worked for me in the past on a Windows platform.
在 Unix 上,您可以使用 valgrind 来查找问题。它免费且功能强大。如果你更愿意自己做,你可以重载 new 和 delete 操作符来设置一个配置,其中0xDEADBEEF
每个新对象前后都有 1 个字节。然后跟踪每次迭代发生的情况。这可能无法捕获所有内容(您甚至不能保证触及这些字节),但它过去在 Windows 平台上对我有用。
回答by David Thornley
Yes, there is a problem with pointers. Very likely you're using one that's not initialized properly, but it's also possible that you're messing up your memory management with double frees or some such.
是的,指针有问题。很可能您使用的是未正确初始化的程序,但也有可能您使用双重释放或类似方法搞乱了内存管理。
To avoid uninitialized pointers as local variables, try declaring them as late as possible, preferably (and this isn't always possible) when they can be initialized with a meaningful value. Convince yourself that they will have a value before they're being used, by examining the code. If you have difficulty with that, initialize them to a null pointer constant (usually written as NULL
or 0
) and check them.
为了避免将未初始化的指针作为局部变量,尝试尽可能晚地声明它们,最好(这并不总是可能)当它们可以用有意义的值初始化时。通过检查代码,说服自己在使用它们之前它们将具有价值。如果您对此有困难,请将它们初始化为空指针常量(通常写为NULL
或0
)并检查它们。
To avoid uninitialized pointers as member values, make sure they're initialized properly in the constructor, and handled properly in copy constructors and assignment operators. Don't rely on an init
function for memory management, although you can for other initialization.
为避免将未初始化的指针作为成员值,请确保它们在构造函数中正确初始化,并在复制构造函数和赋值运算符中正确处理。不要依赖于init
内存管理的函数,尽管您可以进行其他初始化。
If your class doesn't need copy constructors or assignment operators, you can declare them as private member functions and never define them. That will cause a compiler error if they're explicitly or implicitly used.
如果您的类不需要复制构造函数或赋值运算符,您可以将它们声明为私有成员函数并且永远不要定义它们。如果显式或隐式使用它们,则会导致编译器错误。
Use smart pointers when applicable. The big advantage here is that, if you stick to them and use them consistently, you can completely avoid writing delete
and nothing will be double-deleted.
在适用时使用智能指针。这里最大的好处是,如果你坚持使用它们并始终如一地使用它们,你可以完全避免写作,delete
并且不会重复删除任何内容。
Use C++ strings and container classes whenever possible, instead of C-style strings and arrays. Consider using .at(i)
rather than [i]
, because that will force bounds checking. See if your compiler or library can be set to check bounds on [i]
, at least in debug mode. Segmentation faults can be caused by buffer overruns that write garbage over perfectly good pointers.
尽可能使用 C++ 字符串和容器类,而不是 C 风格的字符串和数组。考虑使用.at(i)
而不是[i]
,因为这将强制进行边界检查。看看你的编译器或库是否可以设置为检查边界[i]
,至少在调试模式下。分段错误可能是由缓冲区溢出引起的,缓冲区溢出将垃圾写入完美的指针。
Doing those things will considerably reduce the likelihood of segmentation faults and other memory problems. They will doubtless fail to fix everything, and that's why you should use valgrind now and then when you don't have problems, and valgrind and gdb when you do.
做这些事情将大大减少分段错误和其他内存问题的可能性。他们无疑将无法解决所有问题,这就是为什么您应该在没有问题时不时使用 valgrind,而在有问题时使用 valgrind 和 gdb。
回答by Edward Strange
I don't know of any methodology to use to fix things like this. I don't think it would be possible to come up with one either for the very issue at hand is that your program's behavior is undefined (I don't know of any case when SEGFAULT hasn't been caused by some sort of UB).
我不知道有什么方法可以用来解决这样的问题。我不认为有可能提出一个问题,因为手头的问题是您的程序的行为未定义(我不知道 SEGFAULT 不是由某种 UB 引起的任何情况) .
There are all kinds of "methodologies" to avoid the issue before it arises. One important one is RAII.
有各种各样的“方法”可以在问题出现之前避免它。其中一个重要的就是 RAII。
Besides that, you just have to throw your best psychic energies at it.
除此之外,你只需要投入你最好的精神能量。