我已经编写了一个示例代码来学习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);
}
}
Run Code Online (Sandbox Code Playgroud)
以下是我从上述程序获得的错误消息:
*** 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
Run Code Online (Sandbox Code Playgroud)
任何人都能说出上述错误的原因吗?
IplImage*通过分配cvLoadImage() 必须释放cvReleaseImage().
cvLoadImage()使用malloc()和cvReleaseImage()使用free()来完成工作,同时auto_ptr使用delete(来自C++).
你不能混malloc()在一起delete.
在查看了karlphillip答案的评论后,我将更新此答案以使用,cvReleaseImage。
应该指出的是,您可以通过以下方式完成此操作unique_ptr,因为它可以让您指定自定义删除器:
unique_ptr<IplImage, void(*)(IplImage*)> aptr(cvLoadImage("sample.png"), [](IplImage* temp){cvReleaseImage(&temp);});
Run Code Online (Sandbox Code Playgroud)
这将允许您在不更改的情况下使用自动指针,cvLoadImage并且仍然正确删除内存。
编辑:
unique_ptr是一个拥有的自动指针,这意味着它将执行它的删除器来清理它拥有的分配的内存:https://en.cppreference.com/w/cpp/memory/unique_ptr
auto_ptr与始终调用的不同delete,您可以将自定义删除器传递给unique_ptr.
在 中传递自定义删除器时,unique_ptr您需要向unique_ptr.
所以要分解我的代码:
unique_ptr<IplImage, void(*)(IplImage*)>:这是一个unique_ptr将包含一个IplImage*. 删除器返回void并接受 anIplImage*作为参数。aptr(cvLoadImage("sample.png"),:这个参数需要是一个可管理的指针,它将unique_ptr拥有其所有权,或者是一个nullptr. 显然cvLoadImage正在返回可管理的指针。[](IplImage* temp){cvReleaseImage(&temp);});:这是我传递给的自定义删除器unique_ptr。我将它包装在 lambda 中,这样我就可以unique_ptr根据需要取消引用 Cause所持 cvReleaseImage有的托管指针,以获取指向要删除的引用的指针。