Использование auto_ptr в VC6 DLL вызывает сбой - PullRequest
1 голос
/ 16 апреля 2010
// dll
#include <memory>

__declspec(dllexport) std::auto_ptr<int> get();

__declspec(dllexport) std::auto_ptr<int> get()
{
    return std::auto_ptr<int>(new int());
}

// exe
#include <iostream>
#include <memory>

__declspec(dllimport) std::auto_ptr<int> get();

int main() {
    {
        std::auto_ptr<int> x = get();
    }
    std::cout << "done\n";
    getchar();
}

Следующий код отлично работает под VC9. Однако в VC6 я сразу же столкнусь со следующим сообщением.

Ошибка отладочного подтверждения!

Программа: C: \ Projects \ use_dynamic_link \ Debug \ use_dynamic_link.exe Файл: dbgheap.c Строка: 1044

Выражение: _CrtIsValidHeapPointer (pUserData)

Экспорт auto_ptr под VC6 запрещен?

Известна проблема экспорта классов коллекции STL через DLL.

Нарушение прав доступа при доступе к объекту STL через указатель или ссылку в другой DLL или EXE

Тем не менее, я гуглю вокруг и не вижу ничего упоминания о std :: auto_ptr.

Есть обходной путь?

Ответы [ 4 ]

4 голосов
/ 16 апреля 2010

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

1 голос
/ 16 апреля 2010

Вы нарушаете ODR (одно правило определения), и, скорее всего, функции-члены встроены - так как они встроены в два разных определения std::auto_ptr, вы получаете неопределенное поведение.

Кроме того, как указывает Эдди, когда auto_ptr::~auto_ptr освобождает удерживаемый объект, он вызовет operator delete в EXE-файле, а не в DLL, где был вызван operator new. Это несоответствие также может привести к сбою.

Как правило, экспортировать реализованные классы очень хрупко (классы интерфейса, состоящие исключительно из чисто виртуальных функций и экспортирующие функцию свободной фабрики для конструирования) в порядке, и тогда вы не используете __declspec(dllexport) в классе, только заводская функция.

1 голос
/ 16 апреля 2010

Мое первое предположение было бы, что проекты exe и dll в VC9 настроены для CRT, чтобы быть нацеленным как общая dll, в то время как один или оба проекта VC6 нацелены на статический CRT (не dll).

В качестве альтернативы, и dll, и exe ориентированы на разные версии совместно используемой библиотеки CRT (поэтому они фактически используют 2 разных CRT).

В VC6 проверьте параметр библиотеки времени выполнения в кодеКатегория генерации свойств проекта C / C ++.Убедитесь, что и exe, и dll ориентированы на одну и ту же библиотеку DLL.

0 голосов
/ 16 апреля 2010

OK. Я понимаю коренную причину. Это вызвано

Микропрограмма управления памятью DLL

Смешение менеджера памяти DLL

  1. выделить память из DLL

  2. вернуть указатель на EXE

  3. попытаться удалить указатель из EXE

Шаг (3) будет работать нормально только в том случае, если мы будем динамически ссылаться на библиотеку времени выполнения (в параметрах C / C ++ -> Генерация кода -> Использовать библиотеку времени выполнения)

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...