Pythonセグメンテーション違反の原因は何ですか?


85

KosarajuのStrongConnected Component(SCC)グラフ検索アルゴリズムをPythonで実装しています。

プログラムは小さなデータセットでうまく動作しますが、超大型のグラフ(800,000ノード以上)で実行すると、「セグメンテーション違反」と表示されます。

その原因は何でしょうか?ありがとうございました!


追加情報:最初に、超大規模データセットで実行するとこのエラーが発生しました:

"RuntimeError: maximum recursion depth exceeded in cmp"

次に、を使用して再帰制限をリセットします

sys.setrecursionlimit(50000)

しかし、「セグメンテーション違反」が発生しました

無限ループではなく、比較的小さなデータで正しく実行されると信じてください。プログラムがリソースを使い果たした可能性はありますか?


10
あなたが見て持つことができるかもしれCrashingPython
Abhijit

2
これは純粋なPythonで実行されていますか、それともC拡張モジュールを使用していますか?純粋なPythonの場合は、バグであり、おめでとうございます。ACモジュールを使用している場合、セグメンテーション違反はおそらくそこから発生しています。
aaronasterling 2012

それは純粋なPythonです。プログラムは比較的小さなデータセットでうまく動作し、コードが正しいと思いました。
xiaolong 2012

Pythonのドキュメントによると:
James Thiele 2012

2
Pythonのドキュメントによると::::::可能な上限はプラットフォームによって異なります。深い再帰を必要とするプログラムと、より高い制限をサポートするプラットフォームがある場合、ユーザーは制限をより高く設定する必要がある場合があります。制限が高すぎるとクラッシュする可能性があるため、これは注意して行う必要があります。:::::: OSを指定していません。クラッシュへの言及は、OSのセグメンテーション障害を意味する場合があります。より小さなスタックを試してください。ただし、使用しているアルゴリズムのIIRCは、スタックにrntire SSCを配置するため、スタックが不足する可能性があります。
James Thiele 2012

回答:


80

これは、Python拡張機能(Cで記述)が到達不能なメモリにアクセスしようとしたときに発生します。

次の方法で追跡できます。

  • sys.settraceコードの最初の行に追加します。
  • この回答のマークgdb説明されているように使用してください..コマンドプロンプトで

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

2
おかげで、私のコードは純粋なPythonですが、違いはありますか?
xiaolong 2012

使用しているPythonモジュールを確認しますか?一部のモジュールはPythonで記述されており、その他のモジュールはCで記述されています。バグを報告する必要があると思います。
Shiplu Mokaddim 2012

1
同様の、また役立つ:stdlibのトレースモジュールは、新しい依存関係をインストールしたり、コードを変更したりすることなく、ステージングサーバーのセグメンテーション違反の根底に到達するのに役立ちました。
ドリフトキャッチャー2015年

4
OSX Sierraでは、gdbはlldbに置き換えられました
kthouz 2016

OS Xでは、unconj.ca
blog

54

あなたが問題を解決したことは理解していますが、このスレッドを読んでいる他の人のために、ここに答えがあります:オペレーティングシステムがPythonプロセスに割り当てるスタックを増やす必要があります。

それを行う方法は、オペレーティングシステムに依存します。Linuxでは、コマンドulimit -sで現在の値を確認し、次のコマンドで値を増やすことができます。ulimit -s <new_value>

前の値を2倍にしてみて、機能しない場合は、機能する値またはメモリが不足する値が見つかるまで、2倍を続けます。


また、ulimit maxに直面しているかどうかを確認する良い方法は、実行lsofして使用するgrepwc -l、すべてを追跡することです。
2013

私は同意します。これは、PythonとC ++の両方の実装でセグメンテーション違反を修正することにより、私のKosarajuのSCC実装で実際に機能しました。<br/>私のMACについては、次の方法で可能な最大値を見つけました:
Rock

4
ulimit値は、それが実行される特定のシェルに対してのみ変更されるため、システム全体の値を誤って変更しないことに注意してください
Tanmay Garg 2016

1
これを実行してulimit-s 16384になりましたが、実行後もセグメンテーションエラーが発生しました。
Sreehari R 2017

@SreehariRさらに増やしてみてください。ただし、Python拡張機能(使用している場合)の問題である可能性もあります。これは(この他の回答)[ stackoverflow.com/a/10035594/25891]がデバッグ方法を示唆しています
Davide

18

セグメンテーション違反は一般的なものであり、これには多くの理由が考えられます。

  • 低メモリ
  • 障害のあるRAMメモリ
  • クエリを使用してデータベースから巨大なデータセットをフェッチする(フェッチされたデータのサイズがswap memを超える場合)
  • 間違ったクエリ/バグのあるコード
  • ループが長い(複数回の再帰)

3

ulimitの更新は、Python(Python segfault .. who know!)とC ++の両方の実装でsegfaultを修正することにより、私のKosarajuのSCC実装で機能しました。

私のMACの場合、次の方法で可能な最大値を見つけました。

$ ulimit -s -H
65532

その値を更新する方法は?その値はどのタイプの単位ですか?
パブロ

制限が何である必要があるかをよく知っている場合(そしてプラットフォームがLinuxから変更されることは決してないことがわかっている場合)、python executeコマンドを使用して、コード内からそのコマンドを実行することができます。私は個人的にそれを.bashrcファイルに追加しました。
trumpetlicks

2

グーグル検索は私にこの記事を見つけました、そして私は議論された次の「個人的な解決策」を見ませんでした。


Linux用のWindowsサブシステムでのPython3.7に関する最近の煩わしさは、同じPandasライブラリを持つ2台のマシンで、1台が私segmentation faultに、もう1台が警告を報告することです。どちらが新しいかは明確ではありませんでしたが、「再インストール」pandasすることで問題は解決しました。

バギーマシンで実行したコマンド。

conda install pandas

詳細:同じスクリプト(Gitを介して同期)を実行していましたが、どちらもWSL + Anacondaを搭載したWindows10マシンです。ケースを作るためにスクリーンショットを見てください。また、コマンドラインでpython文句を言うマシンではSegmentation fault (core dumped)、Jupyterlabは毎回カーネルを再起動するだけです。さらに悪いことに、警告はまったく出されませんでした。

ここに画像の説明を入力してください


数か月後の更新:WindowsマシンでのJupyterサーバーのホスティングを終了しました。現在、WindowsでWSLを使用して、Linuxサーバーで開いているリモートポートをフェッチし、すべてのジョブをリモートLinuxマシンで実行しています。私は何ヶ月も実行エラーを経験したことがありません:)


0

RPIでdlibをアップグレードした後、このセグメンテーション違反が発生していました。上記のShipluMokaddimが提案したようにスタックをトレースバックすると、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


-1

スタックメモリが不足しているようです。ダビデが述べたように、あなたはそれを増やしたいと思うかもしれません。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()

出典:codeforcesに関するc1729の投稿。PyPyで実行するのは少し難しいです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.