Чисто виртуальный метод называется кросс-компиляция

Я пишу библиотеку программирования на основе событий для использования на BeagleBone Black и обнаружил странную ошибку.

Когда я компилирую точно такой же код с точно такими же флагами, я получаю следующие ошибки на процессоре на базе ARM, но не когда запускаю код, скомпилированный для моего компьютера x86.

$ ./missionControl
pure virtual method called
pure virtual method called
pure virtual method called
terminate called recursively
terminate called recursively
Aborted

Когда я компилирую и запускаю на своем ноутбуке, программа работает корректно.

Это команда, которую я использую для компиляции (да, я использую Makefile, но оба метода компиляции демонстрируют одинаковое поведение):

g++ -std=gnu++11 -pthread -O3 -D_GLIBCXX_USE_NANOSLEEP -o missionControl `find . -name *.cpp`

Неважно, выполняю ли я кросс-компиляцию с Ubuntu arm-linux-gnueabi-g++ или с ARM-совместимой g++ на реальном BeagleBone, я все равно получаю ошибки на ARM.

Мой вопрос заключается в следующем: что может быть причиной этой ошибки и что я могу сделать, чтобы попытаться найти источник? Почему это происходит на одной процессорной архитектуре, а не на другой, для одной и той же версии G++?

Спасибо!

Вот обратная трассировка из GDB процессора ARM:

#0  0xb6d4adf8 in raise () from /lib/libc.so.6
#1  0xb6d4e870 in abort () from /lib/libc.so.6
#2  0xb6f50ab4 in __gnu_cxx::__verbose_terminate_handler() () from /usr/lib/libstdc++.so.6
#3  0xb6f4ea4c in ?? () from /usr/lib/libstdc++.so.6
#4  0xb6f4ea4c in ?? () from /usr/lib/libstdc++.so.6
Backtrace stopped: previous frame identical to this frame (corrupt stack?)

person Alex Reinking    schedule 15.11.2013    source источник
comment
Вероятно, у вас есть ошибка в управлении временем жизни какого-либо полиморфного объекта или набора объектов. Ошибка обычно появляется, когда вы пытаетесь удалить что-то, что уже было удалено.   -  person Kerrek SB    schedule 16.11.2013
comment
Эта ошибка возникает сразу же, как я запускаю свою программу, прежде чем что-либо будет удалено (я думаю)... Я использую интеллектуальные указатели по всей программе, и valgrind не сообщает об ошибках, и вся память освобождается к концу правильно работающего программа на х86.   -  person Alex Reinking    schedule 16.11.2013
comment
Хм... попробуй уменьшить проблему? Удалить глобальные переменные, пока не заработает? Вы уверены, что ошибка возникает до вызова main?   -  person Kerrek SB    schedule 16.11.2013
comment
@KerrekSB Я не уверен, что это до вызова main(). Позвольте мне попробовать добавить cout прямо вверху main(). Единственная глобальная переменная, которая у меня есть, — это мьютекс в одной единице трансляции, поэтому я попытаюсь учесть это в классе.   -  person Alex Reinking    schedule 16.11.2013
comment
Только что проверил, он определенно входит в main(), так что не должно быть необходимости играть с глобальными переменными, верно?   -  person Alex Reinking    schedule 16.11.2013
comment
У меня точно такая же проблема - я думаю, не так много людей используют std::thread на биглборде, а?   -  person Dave Branton    schedule 23.04.2014


Ответы (3)


Проблема оказалась из-за ошибки в ARM-версии libstdc++, работающей на BeagleBone. Небольшая игрушечная программа, в которой вообще нет виртуальных функций, вызывает ту же ошибку ("вызывается чистая виртуальная функция") при создании std::thread.

Я попытаюсь скомпилировать пользовательскую версию gcc/libstdc++ 4.8 на самом BeagleBone, даже если это займет много времени.

person Alex Reinking    schedule 17.11.2013
comment
В конце концов я стер ужасный Angstrom Linux с BeagleBone и заменил его на Ubuntu. Кросс-компиляция работает, как и ожидалось. Всем, кто использует это замечательное устройство: WIPE и установите вместо него Ubuntu. - person Alex Reinking; 22.04.2014
comment
Вы закончили тем, что пытались собрать gcc? Или вы отказались от этого и сразу перешли на Ubuntu? - person Dave Branton; 23.04.2014
comment
Я пытался собрать gcc. Сборка провалилась на полпути. Я стер его и пошел в Ubuntu. - person Alex Reinking; 23.04.2014

Ошибка вызванный чисто виртуальный метод возникает, когда вы пытаетесь использовать динамическую диспетчеризацию для вызова функции, которая является чисто виртуальной в базе до того, как производный тип, который ее реализует, был сконструирован или уже разрушен.

Наиболее распространенной причиной этого является попытка базового класса вызвать виртуальную функцию, которая является чистой на этом уровне, через конструктор или деструктор. Помимо этого, как было указано в некоторых комментариях, если вы попытаетесь получить доступ к мертвому объекту, вы также можете столкнуться с этой же проблемой.

Просто прикрепите к программе отладчик и посмотрите, какая виртуальная функция вызывается и откуда.

person David Rodríguez - dribeas    schedule 15.11.2013
comment
Не могли бы вы подсказать, как использовать GDB для поиска этой ошибки? Если я позволю ему запуститься и вылететь, обратная трассировка не очень поможет. Я добавил обратную трассировку к моему вопросу. - person Alex Reinking; 16.11.2013
comment
Кроме того, почему это происходит только на ARM? Та же версия компилятора выдает хороший код на x86. - person Alex Reinking; 16.11.2013
comment
Я просто заменил ВСЕ чистые виртуальные функции обычными виртуальными функциями, которые печатают имя функции, а затем вызывают abort(). Я все еще сталкиваюсь с той же проблемой, и сообщения об ошибках, которые я вставил, никогда не печатаются. - person Alex Reinking; 16.11.2013

См.: https://groups.google.com/forum/#!topic/automatak-dnp3/Jisp_zGhd5I

И: Почему этот простой пример потоковой передачи С++ 11 не работает при компиляции с clang 3.2?

Теперь я понятия не имею, почему это работает, но это работает, по крайней мере, для меня. Добавьте следующие четыре определения препроцессора в командную строку компилятора:

__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1
__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2
__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8

Я не экспериментировал, чтобы увидеть, все ли они необходимы, или вы можете обойтись только некоторыми. Но это решило проблему для меня. Спасибо тем, кто написал ответы выше, и спасибо моему коллеге за то, что перегуглил меня :)

person Dave Branton    schedule 23.04.2014