0

我在释放存储在 stl 容器中的 opencv 图像时遇到问题。我正在开发一个系统来保存相机的最后几帧。我需要一个容器来存储图像。但是当我尝试使用迭代器访问图像并释放它们时,事情就出错了。像这样。

deque<IplImage> ImageQue;
IplImage * temp=cvCreateImage(cvSize(30, 30), 8, 3);
ImageQue.push_back(*temp);
deque<IplImage>::iterator it=ImageQue.begin();
//temp and temp2 pointing different mem 
IplImage * temp2=&*it;
//this goes wrong. execption at memory location.
cvReleaseImage(&temp2);

如果我试试这个。

IplImage * try1=cvCreateImage(cvSize(30, 30), 8, 3);
//try1 and try2 are pointing the same mem.
IplImage * try2=&*try1;
//things alright here.
cvReleaseImage(&try2);

我认为问题就在这里。双端队列::迭代器它=ImageQue.begin(); IplImage * temp2=&*it;

对此有任何想法吗?或建议我是否想在 stl 容器中发布图像?

4

3 回答 3

2

看起来你正在混合和匹配你的指针间接。不这样做可能是个好主意:

deque<IplImage> ImageQue; 
IplImage * temp=cvCreateImage(cvSize(30, 30), 8, 3); 
ImageQue.push_back(*temp); 

您可能应该使用指针容器(而不是使用前导大写作为实例名称):

deque<IplImage*> imageQueue; 
imageQueue.push_backcvCreateImage(cvSize(30, 30), 8, 3));
// ...
auto itr = imageQueue.begin();
IplImage* temp = *itr;
cvReleaseImage(&temp);

那类的东西。更重要的是,也许......如果你要像那样销毁你的图像,你应该先把它们从容器中取出,因为你可能不想要一个悬空指针队列。

IplImage* temp  = imageQueue.front();
imageQueue.pop_front();
cvReleaseImage(&temp);

您还可以考虑使用某种智能指针(它会在 IplImage 生命周期结束时自动释放)... OpenCV 的最新版本是否包含用于此类事情的不错的 C++ api,还是我弄错了?Astd::shared_ptr也可以工作,给定一个合适的自定义删除器。

于 2012-06-13T08:04:18.483 回答
1

我不认为 C 接口IplImage喜欢按值复制,就像您尝试做的那样。如果你想使用以值语义操作的 C ++容器,你应该IplImage*使用不必担心释放)。

于 2012-06-13T07:55:59.380 回答
0

您可以使用 C++11 中的 std::shared_ptr 或 C++03 中的 Boost 等效项。

您可以将对象的 shared_ptr 存储在 stl 容器中,但您需要指定删除器(默认为 operator delete)。

您可以在 shared_ptr 的构造函数中分配指针的删除器。在你的情况下 cvReleaseImage 函数。

来自Boost 文档

模板 shared_ptr(Y * p, D d); 模板 shared_ptr(Y * p, D d, A a);

Requirements: p must be convertible to T *. D must be CopyConstructible. 
              The copy constructor and destructor of D must not
              throw. The expression d(p) must be well-formed, must not invoke
              undefined behavior, and must not throw exceptions. A must be an
              allocator, as described in section 20.1.5 (Allocator requirements) of
              the C++ Standard.

Effects: Constructs a shared_ptr that owns the pointer p and the deleter d. 
         The second constructor allocates memory using a copy of a.

Postconditions: use_count() == 1 && get() == p.

Throws: std::bad_alloc, or an implementation-defined 
        exception when a resource other than memory could not be obtained.

Exception safety: If an exception is thrown, d(p) is called.

Notes: When the the time comes to delete the object pointed to by p, 
       the stored copy of d is invoked with the stored copy of p as an
       argument.

[自定义释放器允许工厂函数返回 shared_ptr 以将用户与其内存分配策略隔离开来。由于释放器不是类型的一部分,因此更改分配策略不会破坏源代码或二进制兼容性,并且不需要客户端重新编译。例如,当将 shared_ptr 返回给静态分配的对象时,“no-op”释放器很有用,而其他变体允许将 shared_ptr 用作另一个智能指针的包装器,从而简化互操作性。

对自定义解除分配器的支持不会带来显着的开销。其他 shared_ptr 功能仍然需要保留一个释放器。

D的拷贝构造函数不抛出的要求来自于传值。如果复制构造函数抛出,则指针泄漏。删除要求需要通过 (const) 引用。

引用传递的主要问题在于它与右值的交互。const 引用仍可能导致复制,并且需要 const operator()。非常量引用根本不会绑定到右值。这个问题的一个很好的解决方案是 N1377/N1385 中提出的右值参考。]

于 2012-06-13T08:04:41.583 回答