Що спричиняє помилку сегментації Python?


85

Я впроваджую алгоритм пошуку графіків сильного підключеного компонента (SCC) в Python.

Програма чудово працює на невеликому наборі даних, але коли я запускаю її на надвеликому графіку (понад 800 000 вузлів), у ньому написано "Помилка сегментації".

Що може бути причиною цього? Дякую!


Додаткова інформація: Спочатку я отримав цю помилку під час запуску на надвеликому наборі даних:

"RuntimeError: maximum recursion depth exceeded in cmp"

Потім я скидаю межу рекурсії за допомогою

sys.setrecursionlimit(50000)

але отримав "помилку сегментації"

Повірте, це не нескінченний цикл, він працює правильно на відносно менших даних. Чи можливо програма вичерпала ресурси?


10
Можливо, ви можете подивитися CrashingPython
Abhijit

2
Це працює на чистому Python чи ви використовуєте модуль розширення C? Якщо це чистий Python, то це помилка і вітаю. Якщо ви використовуєте модуль змінного струму, тоді segfault, мабуть, надходить звідти.
aaronasterling

це чистий пітон. Програма чудово працює на відносно невеликому наборі даних, і це змусило мене думати, що код правильний.
xiaolong

Відповідно до документації Python:
Джеймс Тіле

2
Відповідно до документації Python :::::: Найвища можлива межа залежить від платформи. Користувачеві може знадобитися встановити ліміт вище, якщо у нього є програма, яка вимагає глибокої рекурсії, і платформа, яка підтримує більш високий ліміт. Це слід робити обережно, оскільки занадто високий ліміт може призвести до збою. :::::: Ви не вказали ОС. Посилання на аварійне завершення роботи може означати помилку сегментації вашої ОС. Спробуйте менший стек. Але алгоритм IIRC, який ви використовуєте, ставить rntire SSC у стек, щоб у вас не вийшло стека.
Джеймс Тіле,

Відповіді:


81

Це трапляється, коли розширення 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,

Перевірте, які модулі python ви використовуєте? Деякі модулі написані на python, а інші - на C. Я думаю, вам потрібно повідомити про помилку.
Шиплу Мокаддім,

1
подібне, також корисне: модуль трасування stdlib просто допоміг мені дійти до суті помилки сегментації на проміжному сервері, не встановлюючи нової залежності та не змінюючи код.
driftcatcher

4
на OSX Sierra, gdb було замінено на lldb
kthouz


54

Я розумію, що ви вирішили свою проблему, але для інших, хто читає цю тему, ось відповідь: вам потрібно збільшити стек, який ваша операційна система виділяє для процесу python.

Спосіб зробити це залежить від операційної системи. У Linux ви можете перевірити за допомогою команди ulimit -sсвоє поточне значення, а можете збільшити за допомогоюulimit -s <new_value>

Спробуйте подвоїти попереднє значення і продовжуйте подвоювати, якщо воно не працює, поки не знайдете такого, у якого буде або не вистачить пам'яті.


Також хорошим способом перевірити, чи не стикаєтесь ви з обмеженим максимумом, є запуск lsofта використання grepабо wc -lвідстеження всього.
cdated

Я погоджуюсь. Це насправді спрацювало для моєї реалізації SCC від Kosaraju, зафіксувавши segfault як на реалізаціях Python, так і на C ++. <br/> Щодо мого MAC, я дізнався можливий максимум за допомогою:
Rock

4
зауважте, що граничне значення змінюється лише для конкретної оболонки, в якій воно виконується, щоб випадково не змінити значення для всієї вашої системи
Tanmay Garg

1
Я зробив це і в кінцевому підсумку отримав ulimit -s 16384, проте після запуску все одно отримав помилку сегментації.
Sreehari R

@SreehariR Спробуйте збільшити його ще більше. Однак це також може бути проблемою з розширенням python (якщо ви використовуєте будь-яке), що (ця інша відповідь) [ stackoverflow.com/a/10035594/25891] пропонує спосіб налагодження
Davide

18

Помилка сегментації є загальною, тому є багато можливих причин:

  • Низька пам’ять
  • Несправна оперативна пам'ять
  • Отримання величезного набору даних з бази даних за допомогою запиту (якщо розмір отриманих даних перевищує обмін пам’яті)
  • неправильний код запиту / помилки
  • маючи довгий цикл (множинна рекурсія)

3

Оновлення ulimit працювало для реалізації SCC мого Kosaraju, виправляючи segfault як на реалізаціях Python (Python segfault .. хто знав!), Так і на C ++.

Для мого MAC я дізнався можливий максимум за допомогою:

$ ulimit -s -H
65532

як оновити це значення? це значення в якому типі одиниці?
Пабло,

Якщо ви знаєте багато про те, якими вам потрібні ваші обмеження (і ви знаєте, що ваша платформа ніколи не зміниться від Linux), ви можете використовувати команду python execute, щоб просто виконати цю команду з вашого коду. Я особисто додав його до свого файлу .bashrc.
trumpetlicks

2

Пошук у Google знайшов мені цю статтю, і я не побачив обговореного нижче «персонального рішення».


Моє недавнє роздратування з Python 3.7 в підсистемі Windows для Linux полягає в тому, що: на двох машинах з однаковою бібліотекою Pandas одна дає segmentation faultпопередження мені, а інша. Не було зрозуміло, який із них новіший, але "перевстановлення" pandasвирішує проблему.

Команда, що я побіг на баггі-машині.

conda install pandas

Детальніше: я запускав однакові сценарії (синхронізовані через Git), і обидва - це машина Windows 10 з WSL + Anaconda. Ось перейдіть на скріншоти, щоб довести справу. Крім того, на машині, на яку pythonбуде скаржитися командний рядок Segmentation fault (core dumped), лабораторія Jupyter просто перезапускає ядро ​​кожен раз. Гірше того, попередження взагалі не давали.

введіть тут опис зображення


Оновлення через кілька місяців: я кинув розміщувати сервери Jupyter на машині Windows. Тепер я використовую WSL в Windows для отримання віддалених портів, відкритих на сервері Linux, і запуску всіх своїх завдань на віддаленій машині Linux. Я ніколи не стикався з жодною помилкою виконання протягом достатньої кількості місяців :)


0

Я відчув цю помилку сегментації після оновлення dlib на RPI. Я простежив стек, як запропонував Шиплу Мокаддім вище, і він зупинився на бібліотеці 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()

Джерело: допис c1729 про codeforces . Запустити його з PyPy трохи складніше .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.