Что означает "чисто виртуальный" вызов в трассировке стека?
Мой сервис потерпел крах, и я получил этот след стека. Я не могу ничего сделать отсюда
00007f859cd27834 __gnu_cxx::__verbose_terminate_handler()
@ 00007f859cd25865 __cxxabiv1::__terminate(void (*)())
@ 00007f859cd25892 std::terminate()
@ 00007f859cd263be __cxa_pure_virtual
@ 0000000001996f9f My::Class::~Class()
Кто-нибудь может помочь?
2 ответа
Это происходит, если на самом деле была вызвана "чисто виртуальная" функция, что приводит к сбою.
Чистая виртуальная функция объявлена так:
virtual void pureVirtualFunction() = 0;
Обычно компилятор обнаружит, если вы пропустите реализацию чисто виртуальной функции. Но могут быть ситуации, когда это невозможно.
Вызов чистой виртуальной функции в базовом конструкторе
Одной из распространенных проблем являются вызовы функций из базового конструктора класса:
MyClass::MyClass() {
pureVirtualFunction(); // Call of pure virtual function from base constructor.
}
Вызов чистой виртуальной функции в базовом деконструкторе
Или вызов чисто виртуального метода из деконструктора базового класса:
MyClass::~MyClass() {
pureVirtualFunction(); // Call of pure virtual function from base deconstructor.
}
Предварительные декларации общих указателей (и аналогичных)
Существует еще один распространенный случай, если вы используете такие предварительные объявления:
class MyClass;
typedef std::shared_ptr<MyClass> MyClassPtr;
Объект такого общего указателя может быть уничтожен во многих местах, но компилятору не хватает необходимой информации о том, как вызвать деконструктор класса. Убедитесь, что вы прочитали все предупреждения компилятора, он предупредит об этой проблеме (и о многих других проблемах с вызовами чисто виртуальных методов).
Для этого особого случая убедитесь, что вы избегаете предварительных объявлений общих указателей и включаете их только в объявление класса (если это возможно).
Смотрите также этот ответ.
Или более вероятно:
virtual ~Class () = 0;
Это объявляет виртуальный деструктор и говорит компилятору освободить место в vtable для деструктора. Но так как это не определено, GCC вставил вызов __cxa_pure_virtual в vtable.
И когда вам не удалось определить тело для ~Class() или не удалось явно записать его в производный класс, вы вызываете __cxa_pure_virtual при уничтожении.
Вы должны были получить какое-то предупреждение или ошибку при попытке создать экземпляр абстрактного класса.
если немного заглянуть в стек, на самом деле можно получить больше доказательств того, в чем проблема. И примеры кода, демонстрирующие, как вы используете класс, вероятно, будут полезны.