c – 删除在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"));

只要我使用/ MDd设置(VC 2010)编译EXE和DLL,这就完全正常,这意味着EXE和DLL使用相同的堆.

现在我想用/ MTd设置编译我的解决方案.有了这个,我得到了一个类型_CrtIsValidHeapPointer的运行时断言,用于我传递给DLL的设置字符串对象.这是有道理的,因为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函数.

现在一切正常了.但现在我的第一个问题是:当myGrabberObj被删除时,为什么我不能获得_CrtIsValidHeapPointer断言?该对象是从DLL中创建的,但是从EXE中删除(通过智能指针).为什么我在这里遇到与上面的字符串对象相同的问题?

我想一个干净的解决方案是DLL也会导出这样的函数

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

然后我也会在我的EXE中有一个静态函数,它在DLL中调用DeleteGrabber:

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的两个实例(那么这个解决方案根本不能解决我的问题)?或者这两个静态函数使用相同的堆?

我希望有人能解释这里发生了什么……

解决方法

DLL是引用计数,未加载两次,当您使用LoadLibrary时,它只会加载一次,并且它们将使用相同的堆.静态函数是此问题的正常解决方案.

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...