修复 C++ 中的分段错误

发布于 2024-09-24 04:57:25 字数 155 浏览 1 评论 0原文

我正在为 Windows 和 Unix 编写一个跨平台 C++ 程序。在Window端,代码编译和执行没有问题。在 Unix 方面,它会编译,但是当我尝试运行它时,我遇到了分段错误。我最初的预感是指针有问题。

查找和修复分段错误的好方法是什么?

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.

What are good methodologies to find and fix segmentation fault errors?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

如梦亦如幻 2024-10-01 04:57:26

在 Unix 上,您可以使用 valgrind 来查找问题。它是免费且功能强大的。如果您想自己执行此操作,可以重载 newdelete 运算符来设置一个配置,其中之前有 1 个字节的 0xDEADBEEF以及每个新对象之后。然后跟踪每次迭代时发生的情况。这可能无法捕获所有内容(甚至不能保证您触及这些字节),但它过去在 Windows 平台上对我有用。

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.

給妳壹絲溫柔 2024-10-01 04:57:26

是的,指针有问题。很可能您正在使用未正确初始化的内存,但也有可能您通过双重释放或类似操作搞乱了内存管理。

为了避免未初始化的指针作为局部变量,请尝试尽可能晚地声明它们,最好是在可以用有意义的值初始化它们时(这并不总是可能的)。通过检查代码,让自己相信它们在使用之前具有价值。如果您对此有困难,请将它们初始化为空指针常量(通常写为 NULL0)并检查它们。

为了避免将未初始化的指针作为成员值,请确保它们在构造函数中正确初始化,并在复制构造函数和赋值运算符中正确处理。不要依赖 init 函数进行内存管理,尽管您可以进行其他初始化。

如果您的类不需要复制构造函数或赋值运算符,则可以将它们声明为私有成员函数并且永远不要定义它们。如果显式或隐式使用它们,将会导致编译器错误。

适用时使用智能指针。这里的一大优点是,如果您坚持使用它们并始终如一地使用它们,您可以完全避免编写 delete 并且不会出现双重删除。

尽可能使用 C++ 字符串和容器类,而不是 C 风格的字符串和数组。考虑使用 .at(i) 而不是 [i],因为这会强制进行边界检查。查看您的编译器或库是否可以设置为检查 [i] 上的边界,至少在调试模式下如此。分段错误可能是由于缓冲区溢出在完美的指针上写入垃圾而引起的。

做这些事情将大大减少分段错误和其他内存问题的可能性。毫无疑问,它们无法解决所有问题,这就是为什么当你没有问题时你应该时不时地使用 valgrind,当你遇到问题时使用 valgrind 和 gdb。

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.

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.

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.

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.

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.

大姐,你呐 2024-10-01 04:57:26

我不知道有什么方法可以用来解决这样的问题。我认为不可能提出一个,因为当前的问题是你的程序的行为是未定义的(我不知道 SEGFAULT 不是由某种 UB 引起的任何情况) 。

有各种各样的“方法”可以在问题出现之前避免它。其中一个重要的因素是 RAII。

除此之外,你只需要投入你最好的精神能量就可以了。

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).

There are all kinds of "methodologies" to avoid the issue before it arises. One important one is RAII.

Besides that, you just have to throw your best psychic energies at it.

无声情话 2024-10-01 04:57:25
  1. 使用-g编译您的应用程序,然后您将在二进制文件中包含调试符号。

  2. 使用gdb打开gdb控制台。

  3. 使用 file 并向其传递控制台中应用程序的二进制文件。

  4. 使用run并传入您的应用程序启动所需的任何参数。

  5. 执行某些操作会导致分段错误

  6. gdb 控制台中键入 bt 以获取分段错误的堆栈跟踪。

  1. Compile your application with -g, then you'll have debug symbols in the binary file.

  2. Use gdb to open the gdb console.

  3. Use file and pass it your application's binary file in the console.

  4. Use run and pass in any arguments your application needs to start.

  5. Do something to cause a Segmentation Fault.

  6. Type bt in the gdb console to get a stack trace of the Segmentation Fault.

揽清风入怀 2024-10-01 04:57:25

有时崩溃本身并不是问题的真正原因——也许内存在早些时候就被破坏了,但过了一段时间损坏才显现出来。查看 valgrind,它对指针问题进行了大量检查(包括数组边界检查)。它会告诉您问题从哪里开始,而不仅仅是发生崩溃的行。

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.

世界和平 2024-10-01 04:57:25

在问题出现之前,尽量避免它:

  • 尽可能频繁地编译和运行代码。更容易找到故障部分。
  • 尝试封装低级/容易出错的例程,以便您很少需要直接使用内存(注意程序的建模)
  • 维护测试套件。概述当前正在工作的内容、不再工作的内容等,将帮助您找出问题所在(Boost test 是一个可能的解决方案,我自己不使用它,但文档可以帮助理解必须显示什么样的信息)。

使用适当的工具进行调试。在 Unix 上:

  • GDB 可以告诉你程序崩溃的位置,并让你看到在什么地方语境。
  • Valgrind 将帮助您检测许多与内存相关的错误。
  • 使用 GCC,您还可以使用 mudflap 使用 GCC、Clang,从 10 月份开始实验性地 MSVC 您可以使用 地址/内存消毒剂。它可以检测到一些 Valgrind 检测不到的错误,并且性能损失更轻。它通过使用 -fsanitize=address 标志进行编译来使用。

最后我会推荐一些常见的东西。你的程序越是可读、可维护、清晰和整洁,就越容易调试。

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 test is a possible solution, I don't use it myself but the documentation can help to understand what kind of information must be displayed).

Use appropriate tools for debugging. On Unix:

  • GDB can tell you where you program crash and will let you see in what context.
  • Valgrind will help you to detect many memory-related errors.
  • With GCC you can also use mudflap With GCC, Clang and since October experimentally MSVC you can use Address/Memory Sanitizer. It can detect some errors that Valgrind doesn't and the performance loss is lighter. It is used by compiling with the-fsanitize=address flag.

Finally I would recommend the usual things. The more your program is readable, maintainable, clear and neat, the easiest it will be to debug.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文