使用auto_ptr时内存损坏错误

Dee*_*pak 3 c++ opencv

我已经编写了一个示例代码来学习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)

任何人都能说出上述错误的原因吗?

kar*_*lip 5

IplImage*通过分配cvLoadImage() 必须释放cvReleaseImage().

cvLoadImage()使用malloc()cvReleaseImage()使用free()来完成工作,同时auto_ptr使用delete(来自C++).

你不能混malloc()在一起delete.

  • 好问题.你为什么不尝试一下,看看是否有泄漏?或者,您可以花几分钟时间阅读OpenCV源代码并了解`cvReleaseImage()`的作用.让我们知道您的发现. (2认同)

Jon*_*Mee 5

在查看了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有的托管指针,以获取指向要删除的引用的指针。