“分段错误”是系统错误还是程序错误?

“分段错误”是系统错误还是程序错误?

我目前正在运行一个执行系统发育方差分析的统计建模脚本。当我分析完整数据集时,该脚本运行良好。但是,当我获取一个子集时,它开始分析,但很快就会因分段错误而终止。我无法通过谷歌搜索来真正弄清楚这是否可能是由于我这边的问题(例如用于分析的样本数据集太小)和/或脚本中的错误或者这是否与我的Linux系统有关。我读到它与将数据写入内存有关,但是为什么使用更大的数据集一切都很好呢?我尝试使用谷歌查找更多信息,但这使事情变得更加复杂。

感谢您提前澄清!

答案1

(tl;dr:这几乎肯定是您的程序或其使用的库中的错误。)

分段错误表明内存访问不合法。也就是说,根据发出的请求,CPU 会发出页面错误,因为请求的页面不是常驻的,或者具有与请求不一致的权限。

之后,内核检查它是否根本不知道该页面的任何信息,是否它还没有在内存中并且应该将其放在那里,或者是否需要执行一些特殊处理(例如,复制-写页是只读的,这有效的页面错误可能表明我们应该复制它并更新权限)。 参见维基百科对于小调与大调(例如请求寻呼)与无效页面错误。

出现分段错误表示无效情况:该页面不仅不在内存中,而且内核也没有任何要执行的补救操作,因为进程在逻辑上没有映射其虚拟地址空间的该页面。因此,这几乎肯定表明程序或其底层库之一存在错误 - 例如,尝试读取或写入对进程无效的内存。如果地址碰巧有效,则可能会导致堆栈损坏或乱写其他数据,但读取或写入联合国映射的页面被硬件捕获。

它适用于较大的数据集而不是较小的数据集的原因完全特定于该程序:这可能是该程序逻辑中的一个错误,由于某种原因,该错误仅适用于较小的数据集(例如,您的数据集可能有一个表示条目总数的字段,如果未更新,您的程序可能会盲目地读入未分配的内存(如果它不执行其他健全性检查)。

与简单的软件错误相比,它的可能性要小几个数量级,但分段错误也可能是硬件问题的一个指标,例如内存故障、CPU 故障或硬件因勘误而跳闸(例如,请参阅这里)。

由于硬件故障而导致的段错误通常会导致有时无法正常工作的行为,尽管如果您在中间不运行任何其他内容,则在重复运行程序时,物理 RAM 中的坏位可能会以相同的方式映射。您可以通过启动 memtest86+ 检查是否有故障 RAM,并使用 Prime95 等软件对 CPU(包括 FP 数学 FMA 执行单元)进行压力测试来排除这种可能性。


您可以在 gdb 之类的调试器中运行该程序,并在出现分段错误时获取回溯,这可能会指出罪魁祸首:

% gdb --args ./foo --bar --baz
(gdb) r   # run the program
[...wait for segfault...]
(gdb) bt  # get the backtrace for the current thread

答案2

当访问不允许访问的内存位置时,就会发生分段错误。通常,这是由于取消引用空指针或访问已分配内存范围之外的内存。

如果完整数据集有效但子集无效:

  • 检查程序是否优雅地处理数据集不包含特征(也许您根据数据集中现有的特征分配一个数组,但然后根据完整数据集中已知的特征列表假设长度?)
  • 是否有任何组是空的并且会导致问题?一般来说,如果数组为空,会出现任何类型的差一错误吗?

答案3

它可能是由其中任何一个引起的。正如 Chris 所描述的,大多数情况下,这是一个软件错误,但一些硬件问题(尤其是内存故障和电源故障)也可能导致段错误。从内存中读取错误值,这会导致执行损坏的指令、读取损坏的指针、使用损坏的页表等,所有这些都会导致段错误。

但不同之处在于,基于硬件的段错误非常严重。随机的,由几百万分之一的位翻转事件引起(如果系统比这更不稳定,它甚至无法启动)。另一方面,由软件错误引起的段错误可以完全重复。

相关内容