【发布时间】:2013-05-23 17:17:15
【问题描述】:
在一个动态库中分配的内存然后在另一个库中删除通常会引发问题,如Memory allocation and deallocation across dll boundaries 所示。我的问题与 auto_ptr 类型的对象有关。由 dll 提供的这种类型的对象非常棘手,因为使用 dll 的程序会自动删除该对象。但是,经常会发生一些内存重新分配操作可能会发生在 dll 库中的 auto_ptr 类型对象上。因此编写一个销毁 auto_ptr 类型对象的函数是必要的。首先,我给出下面的例子,它说明了在 dll 库中销毁 auto_ptr 类型对象的重要性。
.dll库的头文件如下:
dll.h
class __declspec(dllexport) Image
{
public:
Image()
{
mem = NULL;
}
~Image()
{
std::cout<<"Image is being deleted!"<<std::endl;
delete []mem;
mem = NULL;
}
int *mem;
};
typedef std::auto_ptr<Image> ImagePtr;
class __declspec(dllexport) ImageReader
{
public:
void memory_reset(Image &img)
{
img.mem = new int [20*30];
}
};
调用dll库的可执行程序如下:
#include "dll.h"
#include <iostream>
#include <vector>
#include <numeric>
#include <iostream>
#include <algorithm>
#include <functional>
#include <iterator>
int main()
{
ImagePtr my_img(new Image());
ImageReader bmp_reader;
bmp_reader.memory_reset(*my_img);
return 0;
}
如果调用的运行时库是静态链接的(Multi-threaded Debug (/MTd)),运行可执行程序时会报错:
为了解决这个问题,auto_ptr 对象必须被库删除。那么问题来了:删除这种类型的对象最好的方法是什么?我能想到的办法是提供一个可以删除auto_ptr对象的Global函数:
void Fun_destroy_memory(Image &img)
{
img.~Image();
}
所以可执行程序会变成:
int main()
{
ImagePtr my_img(new Image());
ImageReader bmp_reader;
bmp_reader.memory_reset(*my_img);
Fun_destroy_memory(*my_img);
return 0;
}
我不知道这种情况是否有其他解决方案。另外,我想知道像我在Fun_destroy_memory 中那样直接调用类析构函数是否是一种好习惯。非常感谢!
【问题讨论】:
-
直接调用析构函数是个坏主意。特别是对于 auto_ptr,因为我们知道 auto_ptr 会在某个时候尝试释放此内存。如果析构函数在它拥有的某个托管对象上调用删除操作,您将双重释放此内存。
-
考虑改用
std::unique_ptr<,>(仅限C++11),因为它允许您指定特定的删除函子类型并在您想要的任何位置执行删除。