segfault во время исключения __cxa_allocate_exception в библиотеке SWIG - PullRequest
13 голосов
/ 06 мая 2010

При разработке библиотеки C ++ в оболочке SWIG для Ruby мы столкнулись с необъяснимым сбоем при обработке исключений внутри кода C ++.

Я не уверен в конкретных обстоятельствах для воссоздания проблемы, но это произошло сначала во время вызова std::uncaught_exception, а затем после некоторого изменения кода переместился в __cxa_allocate_exception во время создания исключения. Ни GDB, ни Valgrind не предоставили информации о причине аварии.

Я нашел несколько ссылок на похожие проблемы, в том числе:

Основная тема выглядит как комбинация обстоятельств:

  • Приложение C связано с несколькими библиотеками C ++
  • При компиляции использовалось более одной версии libstdc ++
  • Как правило, вторая используемая версия C ++ происходит из двоичной реализации libGL
  • Проблема не возникает при связывании вашей библиотеки с приложением C ++, только с приложением C

«Решение» состоит в том, чтобы явно связать вашу библиотеку с libstdc ++ и, возможно, также с libGL, форсируя порядок связывания.

После множества попыток с моим кодом, единственное найденное мной решение - это опция LD_PRELOAD="libGL.so libstdc++.so.6" ruby scriptname. То есть ни одно из решений компоновки во время компиляции не имело никакого значения.

Мое понимание проблемы заключается в том, что среда выполнения C ++ не инициализируется должным образом. При форсировании порядка связывания вы запускаете процесс инициализации, и он работает. Проблема возникает только с приложениями C, вызывающими библиотеки C ++, поскольку приложение C само по себе не связывается с libstdc ++ и не инициализирует среду выполнения C ++. Поскольку использование SWIG (или boost :: python) является распространенным способом вызова библиотеки C ++ из приложения C, поэтому SWIG часто возникает при исследовании проблемы.

Кто-нибудь может дать более глубокое понимание этой проблемы? Существует ли реальное решение или существуют только обходные пути?

Спасибо.

Ответы [ 4 ]

6 голосов
/ 17 января 2011

Следуя предложению Майкла Доргана, я копирую свой комментарий в ответ:

Найдена реальная причина проблемы. Надеюсь, это поможет кому-то другому, столкнувшемуся с этой ошибкой. Возможно, у вас где-то есть статические данные, которые не инициализируются должным образом. Мы сделали, и решение было в boost-log для нашей базы кода. https://sourceforge.net/projects/boost-log/forums/forum/710022/topic/3706109. Настоящая проблема - это библиотека с задержкой загрузки (плюс статика), а не потенциально несколько версий C ++ из разных библиотек. Для получения дополнительной информации: http://parashift.com/c++-faq-lite/ctors.html#faq-10.13

С тех пор, как я столкнулся с этой проблемой и ее решением, я понял, что важно понимать, как статические данные разделяются или не разделяются между вашими статически и динамически связанными библиотеками. В Windows это требует явного экспорта символов для общей статики (включая такие вещи, как синглтоны, предназначенные для доступа из разных библиотек). Поведение немного отличается между каждой из основных платформ.

3 голосов
/ 17 декабря 2013

Я недавно тоже столкнулся с этой проблемой.Мой процесс создает модуль общего объекта, который используется как расширение C ++ для Python.Недавнее обновление ОС с RHEL 6.4 до 6.5 выявило проблему.

Следуя приведенным здесь советам, я просто добавил -lstdc ++ к своим переключателям ссылок, и это решило проблему.

1 голос
/ 19 октября 2012

Я понимаю, что @lefticus принял ответ, касающийся, как мне кажется, неопределенного статического порядка инициализации; однако у меня была очень похожая проблема, на этот раз с boost::python.

Я старался изо всех сил, чтобы найти какие-либо проблемы статической инициализации, и не смог - до такой степени, что я рефакторинг основной части нашей кодовой базы; и когда это не сработало, в итоге все исключения были исключены.

Тем не менее, появилось еще немного, и мы снова начали получать эти ошибки.

После еще одного расследования я наткнулся на эту ссылку , в которой говорится о пользовательских распределителях.

Мы действительно используем tcmalloc сами; и после того, как я удалил его из нашей библиотеки, которая экспортируется в boost::python, у нас больше не было проблем!

Так что просто к сведению всех, кто наткнулся на этот поток - если ответ @ lefticus не работает, проверьте, используете ли вы другой распределитель, чем тот, который используется python.

1 голос
/ 25 августа 2012

Имея ту же проблему, используя SWIG для Python с библиотекой cpp (Clipper), я обнаружил, что использование LD_PRELOAD, как вы предлагали, работает и для меня. В качестве другого обходного пути, который не требует LD_PRELOAD, я обнаружил, что я также могу связать libstdc ++ с файлом библиотеки .so моего модуля, например,

ld -shared /usr/lib/i386-linux-gnu/libstdc++.so.6 module.o module_wrap.o -o _module.so

Затем я могу импортировать его в python без каких-либо дополнительных опций.

...