【问题标题】:What causes a Python segmentation fault?是什么导致 Python 分段错误?
【发布时间】:2012-04-19 14:27:47
【问题描述】:

我正在 Python 中实现 Kosaraju 的强连通分量 (SCC) 图搜索算法。

该程序在小数据集上运行良好,但是当我在超大图(超过 800,000 个节点)上运行它时,它显示“Segmentation Fault”。

这可能是什么原因?谢谢!


附加信息: 首先我在超大数据集上运行时遇到了这个错误:

"RuntimeError: maximum recursion depth exceeded in cmp"

然后我使用重置递归限制

sys.setrecursionlimit(50000)

但出现“分段错误”

相信我,这不是一个无限循环,它在相对较小的数据上运行正确。可能是程序耗尽了资源?

【问题讨论】:

  • 也许你可以看看CrashingPython
  • 这是在纯 Python 中运行还是使用 C 扩展模块?如果它是纯 Python,那么它就是一个错误,恭喜你。如果您使用的是 c 模块,那么段错误可能来自那里。
  • 纯python。该程序在相对较小的数据集上运行良好,这让我认为代码是正确的。
  • 根据 Python 文档:
  • 根据 Python 文档:::::: 可能的最高限制取决于平台。当用户有一个需要深度递归的程序和一个支持更高限制的平台时,她可能需要将限制设置得更高。这应该小心完成,因为过高的限制会导致崩溃。:::::: 你没有指定操作系统。对 crash 的引用可能意味着您的操作系统上的 segmentaion fault。尝试较小的堆栈。但是您使用的 IIRC 算法将 rntire SSC 放在堆栈上,因此您可能会用完堆栈。

标签: python segmentation-fault large-data


【解决方案1】:

当 python extension(用 C 编写)试图访问无法访问的内存时,就会发生这种情况。

您可以通过以下方式对其进行跟踪。

  • 在代码的第一行添加sys.settrace
  • 使用gdb,如Markthis answer.. 中所述。在命令提示符处

    gdb python
    (gdb) run /path/to/script.py
    ## wait for segfault ##
    (gdb) backtrace
    ## stack trace of the c code
    

【讨论】:

  • 谢谢,但是我的代码是纯python,有区别吗?
  • 检查你正在使用哪些python模块?有些模块是用python编写的,有些是用C编写的。我认为你需要报告一个错误。
  • 类似,也很有帮助:stdlib 的 trace 模块只是帮助我找到了暂存服务器上的分段错误,而无需安装新的依赖项,也无需修改代码。
  • 在 OSX Sierra 上,gdb 被 lldb 取代
【解决方案2】:

我知道您已经解决了您的问题,但对于阅读此线程的其他人,答案如下:您必须增加操作系统为 python 进程分配的堆栈。

实现方式取决于操作系统。在linux中,您可以使用命令ulimit -s检查您的当前值,您可以使用ulimit -s <new_value>增加它

尝试将先前的值加倍,如果它不起作用,则继续加倍,直到找到一个可以或内存不足的值。

【讨论】:

  • 另外一个检查你是否遇到 ulimit max 的好方法是运行lsof 并使用grepwc -l 来跟踪所有内容。
  • 我同意。通过修复 Python 和 C++ 实现的段错误,这实际上对我的 Kosaraju 的 SCC 实现有效。
    对于我的 MAC,我通过以下方式找到了可能的最大值:
  • 请注意,ulimit 值仅针对执行它的特定 shell 进行修改,因此您不会意外修改整个系统的值
  • 我这样做并以 ulimit -s 16384 结束,但是运行后我仍然遇到分段错误。
  • @SreehariR 尝试进一步增加它。然而,它也可能是 python 扩展的问题(如果你使用任何),它(这个其他答案)[stackoverflow.com/a/10035594/25891] 建议如何调试
【解决方案3】:

Segmentation fault 是通用的,有很多可能的原因:

  • 内存不足
  • 内存故障
  • 使用查询从数据库中获取大量数据集(如果获取的数据大小超过交换内存)
  • 查询错误/错误代码
  • 具有长循环(多次递归)

【讨论】:

    【解决方案4】:

    通过修复 Python(Python segfault.. 谁知道!)和 C++ 实现上的段错误,更新 ulimit 对我的 Kosaraju 的 SCC 实现有效。

    对于我的 MAC,我通过以下方式找到了可能的最大值:

    $ ulimit -s -H
    65532
    

    【讨论】:

    • 如何更新该值?这个值是什么类型的单位?
    • 如果你对你需要的限制有很多了解(并且你知道你的平台永远不会离开 linux),你可以使用 python 执行命令从你的内部简单地执行该命令代码。我个人已将其添加到我的 .bashrc 文件中。
    【解决方案5】:

    谷歌搜索找到了我这篇文章,并没有看到下面讨论的“个人解决方案”。


    我最近对适用于 Linux 的 Windows 子系统上的 Python 3.7 的烦恼是:在两台具有相同 Pandas 库的机器上,一台给我segmentation fault,另一台报告警告。目前尚不清楚哪个更新,但“重新安装”pandas 解决了这个问题。

    我在有问题的机器上运行的命令。

    conda install pandas
    

    更多详细信息:我正在运行相同的脚本(通过 Git 同步),并且两者都是带有 WSL + Anaconda 的 Windows 10 机器。这里是截图来说明情况。此外,在命令行python 会抱怨Segmentation fault (core dumped) 的机器上,Jupyter 实验室每次都会简单地重新启动内核。更糟糕的是,根本没有发出警告。


    几个月后的更新:我不再在 Windows 机器上托管 Jupyter 服务器。我现在在 Windows 上使用 WSL 来获取在 Linux 服务器上打开的远程端口,并在远程 Linux 机器上运行我的所有作业。我已经好几个月没有遇到任何执行错误了:)

    【讨论】:

      【解决方案6】:

      在 RPI 上升级 dlib 后,我遇到了这个分段错误。 我按照上面 Shiplu Mokaddim 的建议对堆栈进行了回溯,并确定了一个 OpenBLAS 库。

      由于 OpenBLAS 也是多线程的,因此在多线程应用程序中使用它会成倍增加线程,直到出现分段错误。对于多线程应用程序,请将 OpenBlas 设置为单线程模式。

      在python虚拟环境中,通过编辑告诉OpenBLAS只使用一个线程:

          $ workon <myenv>
          $ nano .virtualenv/<myenv>/bin/postactivate
      

      并添加:

          export OPENBLAS_NUM_THREADS=1 
          export OPENBLAS_MAIN_FREE=1
      

      重新启动后,我能够在 rpi3b 上运行我之前崩溃的所有图像识别应用程序。

      参考: https://github.com/ageitgey/face_recognition/issues/294

      【讨论】:

        【解决方案7】:

        看起来您的堆栈内存不足。正如戴维德所说,您可能希望增加它。要在 python 代码中执行此操作,您需要使用线程运行“main()”:

        def main():
            pass # write your code here
        
        sys.setrecursionlimit(2097152)    # adjust numbers
        threading.stack_size(134217728)   # for your needs
        
        main_thread = threading.Thread(target=main)
        main_thread.start()
        main_thread.join()
        

        来源:c1729's post on codeforces。用 PyPy 运行它有点trickier

        【讨论】:

          【解决方案8】:

          我会遇到同样的错误。我从another SO answer了解到,需要通过sysresource模块设置递归限制。

          【讨论】:

          • 您的答案可以通过额外的支持信息得到改进。请编辑以添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。您可以在帮助中心找到更多关于如何写出好的答案的信息。 ——
          猜你喜欢
          • 1970-01-01
          • 2020-09-15
          • 1970-01-01
          • 1970-01-01
          • 2018-06-17
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多