Удаление объекта, созданного в DLL

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

В моем проекте DLL (которая определяется ее именем) возвращает новый объект Grabber. В более ранней версии моего кода DLL экспортировала функцию, подобную этой:

extern "C"
__declspec(dllexport) Grabber* CreateGrabber(string settings)
{
    return new SomeSpecificGrabber(settings);
}

В EXE я использовал подобную статическую функцию для создания нового объекта Grabber:

static Grabber* createGrabberObject(const std::string& grabberType, const std::string& grabberSettings)
{
    FARPROC hProc = 0;

    // load dll with the name of grabberType
    HMODULE hDLL = LoadLibrary(grabberType.c_str());

    // get address for CreateGrabber function
    hProc = GetProcAddress(hDLL, "CreateGrabber");

    // instantiate a function pointer of our type and typecast the address
    // of the CreateGrabber function to this type
    CreateGrabberFunctionType CreateGrabberFunction = (CreateGrabberFunctionType)hProc;

    // call CreateGrabber in DLL to get a Grabber object
    return CreateGrabberFunction(grabberSettings);
}

В EXE время жизни объекта Grabber управляется умным указателем:

shared_ptr<Grabber> myGrabberObj = shared_ptr<Grabber>(createGrabberObject("SomeGrabber.DLL", "Settings"));

Все это работало нормально, пока я компилировал EXE и DLL с настройкой / MDd (VC ++ 2010), что означает, что EXE и DLL использовали одну и ту же кучу.

Теперь я хочу скомпилировать свое решение с помощью / MTd . Благодаря этому я получил утверждение времени выполнения типа _CrtIsValidHeapPointer для строкового объекта настроек, который я передал в DLL. Это делает s ense, потому что DLL пытается удалить строковый объект, созданный в EXE. И они больше не используют одну и ту же кучу.

Я решил эту проблему, немного изменив экспортируемую функцию DLL ( const char * вместо string ):

extern "C"
__declspec(dllexport) Grabber* CreateGrabber(const char* settings)
{
    return new SomeSpecificGrabber(settings);
}

А в createGrabberObject я передаю grabberSettings.c_str () вместо grabberSettings функции DLL.

Теперь все снова работает нормально. Но теперь возникает мой первый вопрос : Почему я не получаю утверждение _CrtIsValidHeapPointer , когда myGrabberObj удален? Объект был создан из библиотеки DLL, но удален из EXE (интеллектуальным указателем). Почему у меня здесь нет той же проблемы, что и со строковым объектом выше?

Думаю, лучшим решением было бы то, что DLL также экспортирует функцию, подобную этой:

extern "C"
__declspec(dllexport) void DeleteGrabber(Grabber* grabber)
{
    delete grabber;
}

Тогда у меня также будет статическая функция в моем EXE, который вызывает DeleteGrabber в DLL:

static void deleteGrabberObject(const std::string& grabberType, Grabber* grabber)
{
    FARPROC hProc = 0;

    // load dll with the name of grabberType
    HMODULE hDLL = LoadLibrary(grabberType.c_str());

    // get address for DeleteGrabber function
    hProc = GetProcAddress(hDLL, "DeleteGrabber");

    // instantiate a function pointer of our type and typecast the address
    // of the DeleteGrabber function to this type
    DeleteGrabberFunctionType DeleteGrabberFunction = (DeleteGrabberFunctionType)hProc;

    // call DeleteGrabber in DLL
    DeleteGrabberFunction(grabber);
}

Эта статическая функция может затем автоматически вызываться интеллектуальным указателем:

shared_ptr<Grabber> myGrabberObj = shared_ptr<Grabber>(createGrabberObject("SomeGrabber.DLL", "Settings"), 
boost::bind(deleteGrabberObject, "SomeGrabber.DLL", _1));

Это также работает. Но вот мой второй вопрос : статические функции createGrabberObject и deleteGrabberObject загружают DLL. Означает ли это, что создаются две разные кучи, потому что загружены два экземпляра DLL (тогда это решение вообще не решило бы мою проблему)? Или эти две статические функции используют одну и ту же кучу?

Надеюсь, кто-нибудь сможет объяснить, что здесь происходит ...

7
задан Robert Hegner 20 July 2011 в 13:41
поделиться