跨DLL的内存/堆管理

msi*_*msi 20 c++ dll memory-management

虽然它似乎是一个非常常见的问题,但我没有收集到太多信息:如何在DLL边界之间创建有关内存分配的安全接口?

众所周知

// in DLL a
DLLEXPORT MyObject* getObject() { return new MyObject(); }
// in DLL b 
MyObject *o = getObject();
delete o;
Run Code Online (Sandbox Code Playgroud)

肯定会导致崩溃.但是,由于像上面那样的交互 - 我敢说 - 并不罕见,因此必须有一种方法来确保安全的内存分配.

当然,人们可以提供

// in DLL a
DLLEXPORT void deleteObject(MyObject* o) { delete o; }
Run Code Online (Sandbox Code Playgroud)

但也许有更好的方法(例如smart_ptr?).我也读到了在处理STL容器时使用自定义分配器的问题.

所以我的调查更多的是关于处理这个主题的文章和/或文献的一般指示.是否存在需要注意的特殊谬误(异常处理?)并且这个问题仅限于DLL还是"受到"的UNIX共享对象?

Bjö*_*lex 13

正如您所建议的那样,您可以使用boost :: shared_ptr来处理该问题.在构造函数中,您可以传递自定义清理函数,该函数可以是创建指针的dll的deleteObject-Method.例:

boost::shared_ptr< MyObject > Instance( getObject( ), deleteObject );
Run Code Online (Sandbox Code Playgroud)

如果您的dll不需要C接口,则可以getObject返回shared_ptr.

  • 这也是Effective C++中推荐的内容. (2认同)

Ale*_*ler 9

超载operator new,operator delete等.为您的所有DLL类,并在DLL中实现它们:

 void* MyClass::operator new(size_t numb) {
    return ::operator new(num_bytes);
 }

 void MyClass::operator delete(void* p) {
    ::operator delete(p);
 }
 ...
Run Code Online (Sandbox Code Playgroud)

这可以很容易地放在DLL导出的所有类的公共基类中.

这样,分配和释放完全在DLL堆上完成.老实说,我不确定它是否有任何严重的陷阱或可移植性问题 - 但它对我有用.


MSa*_*ers 5

你可能会说它"肯定会导致崩溃".有趣 - "可能"意味着与"肯定"完全相反.

现在,无论如何,声明大部分都是历史性的.有一个非常简单的解决方案:使用1个编译器,1个编译器设置,并链接到CRT的DLL形式.(你可以逃脱后者)

没有特定的文章可以链接到,因为现在这是一个非问题.无论如何,你需要1个编译器,1个设置规则.简单的事情sizeof(std::string)取决于它,否则你会发生大规模的ODR违规.