Несовместимый оператор нового / удаления вызова - PullRequest
2 голосов
/ 21 января 2010

У меня возникли проблемы с динамически связанной библиотекой, вызывающей мой перегруженный оператор delete, но не мой оператор new. Мой exe выглядит примерно так:

class A {
public:
    void func() {
        t = dynLib::Type::CreateObject();
    }
    dynLib::Type t;
};

void main() {
    A a;
    a.func();
}

А потом у меня есть статически связанная библиотека, где у меня есть глобальные перегруженные операторы. и динамически связанная библиотека, которая вызывает проблему. По сути, тип dynLib :: Type содержит std :: vector, к которому он добавляет элемент в свой конструктор. Так что тип выглядит примерно так

class Type {
public:
    Type() {
        v.push_back( T() );
    }

    std::vector< T > v;
};

Когда вызывается func (), создается новый экземпляр Type, передается по значению, а затем присваивается t. Оператор = в работе копирует std :: vector также через его оператор =. Это, в свою очередь, вызывает освобождение старого std :: vector в t, поскольку в его конструкторе уже был добавлен элемент. Этот вызов освобождения заканчивается вызовом моего оператора delete. Проблема в том, что мой оператор new никогда не вызывался, поэтому он удаляет указатель в совершенно другом пространстве памяти (логирование памяти показывает это).

Теперь я, наверное, просто что-то упустил. Так как класс A выше содержит объект dynLib :: Type, он может быть создан до того, как мой оператор new (из статической библиотеки) будет связан. Это вообще возможно? Я не совсем уверен, в какой момент вызывается конструктор составного dynLib :: Type. Динамическая библиотека использует распределители stl по умолчанию, поэтому она не делает ничего прикольного.

Я пытался воссоздать ту же ситуацию без динамически связанной библиотеки, просто используя класс Type в моем exe-файле. Это не вызывает проблемы, поэтому заставляет меня думать, что это как-то связано с порядком ссылок.

1 Ответ

1 голос
/ 21 января 2010

Это плохо. Вы фактически используете объекты STL через границу DLL. Это большое нет-нет, и оно будет вызывать головные боли у вас. Наиболее вероятным источником проблем со связыванием является то, как исполняемый файл и DLL используют CRT. Если один использует статический (/ MT), а другой - динамический (/ MD), вы увидите все виды странностей, и перегруженный оператор new обычно дает первый сбой.

Если CRT согласован по всем направлениям, он должен работать, но все равно не рекомендуется использовать DLL, как если бы это была статическая библиотека.

Попробуйте реорганизовать код, чтобы вам не приходилось создавать Type вне DLL, посмотрите, не улучшит ли это его.

...