Почему я получаю исключение в dynamic_cast после заполнения объекта нулями с помощью memset - PullRequest
2 голосов
/ 28 мая 2020

Я получаю это странное исключение во время выполнения с dynamic_cast, но только если я заполняю объект, который я кастую, нулями, используя memset, или просто копирую в него некоторые данные с помощью memcpy. Вот пример, который генерирует исключение.

class Base
{
public:
    virtual void func() { }
};

class Derived : public Base
{
public: 
    void func() override { }    
};

int main()
{   
    Derived derived;
    Base* base_ptr = &derived;
    memset(base_ptr, 0, sizeof(Derived));

    Derived* derived_ptr = dynamic_cast<Derived*>(base_ptr);    
}

И сообщение об исключении: enter image description here

Я получаю такое же исключение, если копирую одно Derived возражать другому, используя memcpy. Кто-нибудь знает, что происходит, это портит RTTI, который использует dynamic_cast?

Я делаю игровой движок, и в нем есть система компонентов сущностей, и в какой-то момент программы я загружаю все объекты и их компоненты из файла. Я реализовал различные компоненты с помощью наследования (каждый компонент является производным от одного базового компонента). Когда я загружаю объекты и их компоненты, я не могу просто выделить объем памяти, который занимает компонент, я должен использовать новое имя компонента , потому что только тогда работает dynamic_cast.

Я с использованием Visual Studio 2019.

Ответы [ 2 ]

5 голосов
/ 28 мая 2020

Ваш код имеет неопределенное поведение. memset требует, чтобы объект, который он устанавливает, был TriviallyCopyable , что не является вашим, потому что у него есть виртуальные функции.

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

3 голосов
/ 28 мая 2020

Класс с виртуальными методами часто имеет скрытый член-указатель для vtable. Используя memset, вы уничтожаете этот указатель.

Скрытый указатель не требуется спецификацией языка C ++, но это, безусловно, наиболее распространенный способ реализации виртуальных методов и RTTI.

...