在一个动态库中分配的内存然后在另一个库中删除通常会引发问题,如 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 超出范围时,他们管理的对象将被释放。您无法控制您不使用“new”创建的任何变量的“生命周期”。因此,没有办法销毁这个“auto_ptr”,它只会超出范围。如果您遇到此对象的范围问题,并且您确定这是问题所在(显然我不相信),您可以使用任意范围解析运算符概述代码部分,以管理某些变量的范围。我复制了您的代码来创建示例。
int main()
{
//Do some work that doesn't need an ImagePtr
ImageReader bmp_reader;
{
ImagePtr my_img(new Image());
bmp_reader.memory_reset(*my_img);
} // the my_img pointer is no longer in scope and it's manage object will be freed
return 0;
}
请注意,我不一定推荐这样做,坦率地说,我认为它看起来很糟糕,而且您的问题出在其他地方。但是,如果您绝对相信与“bmp_reader”相比管理“my_img”的生命周期会有所帮助,那么这就是您的做法。
为什么不直接修改 memory_reset。如果一个对象/函数“控制”了一个对象,并对其托管内存执行某些操作,则它有责任确保在将此指针的值分配给其他对象之前释放内存。我会推荐以下内容。
void memory_reset(Image &img)
{
delete[] img.mem; //add this line
img.mem = new int [20*30];
}
另请注意,在同一环境中将托管/垃圾收集/智能指针与新建/删除内存管理类型的方案混合使用通常被认为是糟糕的编程实践。
关于c++ - 如何删除 C++ dll 中 auto_ptr 类型的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16720098/