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

TUn*_*nix 14 segmentation-fault

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

感谢您提前澄清!

Chr*_*own 36

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

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

之后,内核会检查它是否根本不知道有关此页面的任何信息,它是否只是不在内存中而应该将其放在那里,或者它是否需要执行一些特殊处理(例如,copy-on -write 页面是只读的,这个有效的页面错误可能表明我们应该复制它并更新权限)。 请参阅维基百科以了解次要与主要(例如需求分页)与无效页面错误。

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

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

与简单的软件错误相比,它的可能性要低几个数量级,但分段错误也可能是硬件问题的一个指标,例如内存故障、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
Run Code Online (Sandbox Code Playgroud)

  • _几乎_可以肯定,是的,但它也可能表示物理内存错误。这在激进超频的鼎盛时期更为常见。 (2认同)
  • 在 Linux 上,您可能还想尝试在 [valgrind](https://valgrind.org/) 下运行,这通常会为您提供有关 *为什么* 发生内存错误的一些信息。尽管在这种情况下听起来可能只是访问错误,但可能还有其他未发现的问题导致了该问题。gdb 的优点是能够深入内部;valgrind 的优点是观察你的程序正在做什么并报告某些类型的不当行为。(例如,如果程序首先访问释放的内存,gdb 可能不会注意到,但 valgrind 会。) (2认同)

小智 5

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

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

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