Что означает "чисто виртуальный" вызов в трассировке стека?

Мой сервис потерпел крах, и я получил этот след стека. Я не могу ничего сделать отсюда

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 при уничтожении.

Вы должны были получить какое-то предупреждение или ошибку при попытке создать экземпляр абстрактного класса.

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

Другие вопросы по тегам