当前位置: 首页 > 知识库问答 >
问题:

为什么分段故障不可恢复?

柯立果
2023-03-14

顺着我之前的一个问题,大部分评论都说“就是不要,你处于冷宫状态,你要杀光一切,重新开始”。还有一个“安全”的变通方法。

我不明白的是为什么分割错误本质上是不可恢复的。

写入受保护内存的时刻被捕获-否则,不会发送SIGSEGV

如果能够捕捉到写入受保护内存的时刻,我不明白为什么——理论上——它不能在某个低级别上恢复,并将SIGSEGV转换为标准软件异常。

请解释为什么在出现分段错误后,程序处于不确定状态,因为很明显,错误是在内存实际更改之前抛出的(我可能错了,不明白为什么)。如果它被抛出后,人们可以创建一个程序,改变受保护的内存,一次一个字节,获得分段错误,并最终重新编程内核-一个不存在的安全风险,因为我们可以看到世界仍然存在。

  1. 分段错误到底是什么时候发生的(=isSIGSEGVsend)?
  2. 为什么进程在该点之后处于未定义的行为状态?
  3. 为什么无法恢复?
  4. 为什么此解决方案可以避免不可恢复状态?是吗

共有3个答案

东郭弘
2023-03-14

关于分段错误,您必须了解的是,它们不是问题。他们是上帝近乎无限仁慈的一个例子(根据我在大学时的一位老教授)。分段错误是某种严重错误的标志,您的程序认为在没有内存的地方访问内存是个好主意。这种准入本身不是问题;问题出现在之前某个不确定的时间,当出现问题时,最终导致您的程序认为这种访问是一个好主意。在这一点上,访问不存在的内存只是一种症状,但(这就是主的仁慈之所在)这是一种很容易发现的症状。情况可能更糟;它可能是在有内存的地方访问内存,只是错误的内存。操作系统救不了你。

操作系统无法找出是什么导致你的程序相信如此荒谬的事情,它唯一能做的就是在它做其他操作系统无法轻易检测到的疯狂事情之前关闭它。通常,大多数操作系统还提供一个核心转储(程序内存的保存副本),理论上可以用来找出程序认为它在做什么。对于任何非平凡的程序来说,这并不简单,但这就是操作系统这样做的原因,以防万一。

吴升
2023-03-14

请解释为什么在出现分段故障后,程序处于未确定状态

我认为这是你根本的误解——SEGV不会导致不确定状态,它只是一种症状。所以问题是(通常)程序在SIGSEGV发生之前就处于非法、不可恢复的状态,从SIGSEGV恢复不会改变这一点。

  • 分割错误发生的确切时间(=SIGSEGV发送时)?

发生SIGSEGV的唯一标准方式是调用lave(SIGSEGV);。如果这是SIGSEGV的来源,那么它显然可以通过使用跳远来恢复。但这是现实中从未发生过的微不足道的案件。有一些特定于平台的方法可能会导致定义良好的SEGV(例如,在POSIX系统上使用mprotected),这些SEGV可能是可恢复的(但可能需要特定于平台的恢复)。然而,与未定义行为相关的SEGV的危险通常意味着信号处理器将非常仔细地检查随信号而来的(与平台相关的)信息,以确保它是预期的。

  • 为什么进程在该点之后处于未定义的行为状态

在该点之前,它(通常)处于未定义的行为状态;只是没人注意到。这是C和C中未定义行为的一个大问题——没有与之相关的特定行为,因此可能不会立即被注意到。

  • 为什么这个解决方案避免了不可恢复的状态?它甚至吗?

它没有,它只是回到了以前的某个点,但是没有做任何事情来撤销甚至识别导致问题的未定义行为。

吉玉石
2023-03-14

分割错误到底发生在什么时候(=SIGSEGV发送时)?

当您试图访问您无权访问的内存时,例如访问越界数组或取消引用无效指针。信号SIGSEGV是标准化的,但是不同的操作系统可能会以不同的方式实现它。“分段故障”主要是*nix系统中使用的术语,视窗称之为“访问违规”。

为什么进程在那之后处于未定义的行为状态?

因为程序中的一个或多个变量的行为不符合预期。假设您有一个数组,它应该存储许多值,但是您没有为所有值分配足够的空间。因此,只有那些您分配了空间的对象才能正确写入,而在数组边界之外写入的其余对象可以保存任何值。操作系统如何确切地知道这些越界值对于应用程序的运行有多重要?它对他们的目的一无所知。

此外,在允许的内存之外写入通常会损坏其他不相关的变量,这显然是危险的,并可能导致任何随机行为。这种漏洞通常很难追踪。例如,堆栈溢出是这样的分段错误,容易覆盖相邻的变量,除非错误被保护机制捕获。

如果我们看一下“裸机”微控制器系统的行为,没有任何操作系统,没有虚拟内存功能,只有原始物理内存-它们将完全按照指示默默地执行-例如,覆盖不相关的变量并继续。如果应用程序是任务关键型的,这反过来可能会导致灾难性的行为。

为什么它不能恢复?

因为操作系统不知道你的程序应该做什么。

尽管在上面的“裸机”场景中,系统可能足够智能,可以将自身置于安全模式并继续运行。汽车和医疗技术等关键应用不允许仅仅停止或重置,因为这本身可能是危险的。他们宁愿尝试在功能有限的情况下“跛行回家”。

为什么这个解决方案避免了不可恢复的状态?它甚至吗?

这个解决方案就是忽略错误,继续前进。它不能解决导致它的问题。这是一个非常脏的补丁,setjmp/long jmp通常都是非常危险的函数,无论出于什么目的都应该避免。

我们必须意识到分割错误是错误的症状,而不是原因。

 类似资料:
  • 问题内容: 我有一个用于捕获任何分段错误或ctrl- c的应用程序。使用下面的代码,我能够捕获分段错误,但是该处理程序一次又一次地被调用。我该如何阻止他们。供您参考,我不想退出我的申请。我只是可以小心释放所有损坏的缓冲区。 可能吗? 处理程序就是这样。 在这里,对于Segmentation故障信号,处理程序被多次调用,并且很明显MyfreeBuffers()给我释放已释放的内存的错误。我只想释放一

  • 我有一个便宜的5美元/月的服务器,1G内存为我的网站处理一些图像。在将GIF图像写入磁盘时,我很少会遇到PHP Imagick的分割错误。 我在console命令上设置了一个内存限制,希望PHP能够首先捕获这个问题,并抛出一个我可以正确处理的异常,但这不起作用。 特别的问题是某些GIF图像会导致它在这行代码中崩溃: 特定的GIF是与成人相关的GIF,因此我不确定是否可以共享它。 以下是我的服务器日

  • 我有一个应用程序,我用它来捕捉任何分割错误或ctrl-c。使用下面的代码,我能够捕获分段错误,但是处理程序被一次又一次地调用。我怎样才能阻止他们。告诉你,我不想退出我的申请。我只是可以小心释放所有损坏的缓冲区。 可能吗? handler是这样的。 这里的分段故障信号,处理程序被多次调用,因为明显的MyFreeBuffers()给我释放已经释放的内存的错误。我只想免费一次,但仍然不想退出应用程序。

  • 分段错误发生在 运行Glewinfo 运行VisualInfo 测试程序(详细信息如下) 调用glGetProgramInterfaceiv(详细信息如下) 使用gdb实现glewinfo的堆栈跟踪 使用gdb实现visualinfo的堆栈跟踪 下面是使用已安装的GLEW库和glfw3(3.0.3)的测试程序 编译: 运行前。/basic I设置 (否则我会得到分段错误,因为它试图使用安装的GLE

  • 我正在构建一个Qt应用程序,它因为分段错误而崩溃。经过调查,我发现segfault的原因是“this”为空,我试图访问readInputFile(QString path)方法中的成员变量。在这一行中,

  • 我正在尝试用Objective-C编写一个波阵面OBJ文件查看器,它能够从文件中加载网格/材质/着色器。我已经为着色器和着色器程序创建了类,我正在尝试创建一个OpenGL着色器程序对象,作为着色器程序类的init方法的一部分: 但是,调用glCreateProgram会导致EXC_BAD_访问,调用[SRShader compile]也会导致EXC_BAD_访问,而[SRShader compil