我已经编写了一个示例代码来学习auto_ptr的工作,但是当我运行示例代码时,我的内存损坏了。
我的示例代码如下:
#include <iostream>
#include <memory>
#include <cv.h>
#include <highgui.h>
using namespace std;
int main()
{
for (int i = 0; i < 1000; i++)
{
IplImage* temp = cvLoadImage("sample.png");
auto_ptr<IplImage> aptr (temp);
}
}
以下是我从上述程序中收到的错误消息:
*** glibc detected *** ./a.out: double free or corruption (out): 0x00000000008325c0 ***
======= Backtrace: =========
/lib64/libc.so.6[0x36eb276166]
/lib64/libc.so.6[0x36eb278ca3]
./a.out[0x400e9b]
./a.out[0x400df7]
/lib64/libc.so.6(__libc_start_main+0xfd)[0x36eb21ed1d]
./a.out[0x400cf9]
======= Memory map: ========
00400000-00402000 r-xp 00000000 00:19 7879127
有人可以说出上述错误的原因吗?
答案 0 :(得分:5)
IplImage*
分配的 cvLoadImage()
必须
cvReleaseImage()
一起发布。
cvLoadImage()
使用malloc()
而cvReleaseImage()
使用free()
来完成工作,而auto_ptr
则使用delete
(来自C ++)。
您无法将malloc()
与delete
混合。
答案 1 :(得分:4)
在查看有关karlphillip的答案的评论后,我将更新此答案以使用cvReleaseImage
。
应该指出,您可以使用unique_ptr
完成此操作,因为它可以让您指定自定义删除器:
unique_ptr<IplImage, void(*)(IplImage*)> aptr(cvLoadImage("sample.png"), [](IplImage* temp){cvReleaseImage(&temp);});
这将允许您使用自动指针而不更改cvLoadImage
并仍然正确删除内存。
修改强>
unique_ptr
是一个拥有自动指针,这意味着它将执行它的删除工具来清理它拥有的已分配内存:https://en.cppreference.com/w/cpp/memory/unique_ptr
与总是调用auto_ptr
的{{1}}不同,您可以将自定义删除工具传递给delete
。
在unique_ptr
中传递自定义删除时,您需要向unique_ptr
提供仿函数签名。
所以要打破我的代码:
unique_ptr
:这是unique_ptr<IplImage, void(*)(IplImage*)>
,其中包含unique_ptr
。删除器返回IplImage*
并以void
作为参数。IplImage*
:这个参数需要是一个可管理的指针,aptr(cvLoadImage("sample.png"),
将取得所有权,或unique_ptr
。显然nullptr
正在返回可管理的指针。cvLoadImage
:这是我传递给[](IplImage* temp){cvReleaseImage(&temp);});
的自定义删除工具。我将它包装在lambda中,因此我可以取消引用由unique_ptr
导致的托管指针,因为this unique_ptr
需要指向要删除的引用。< / LI>