1

I'm writing my first opencv code(and first C++ code actually), and met with a strange munmap_chunk(): invalid pointer error when I try to use cv::Ptr. I see in other posts that this usually results from freeing a already freed area, but I think I didn't.

The following simple testing function will generate that error.

void testing(void) {
    int i=2;
    Ptr< Mat > pointer=new Mat[i];
}

From the debugger, it seems that the destructor triggers the error when the function returns.I couldn't figure out why since basically I did nothing with the Ptr. So why this is happening and what's the correct usage?

Thanks in advance.

Dorian
  • 1,439
  • 1
  • 11
  • 26
btshengsheng
  • 703
  • 5
  • 12
  • do **not** use any kind of pointers with cv::Mat. it already is a smartpointer on its own. pass references or even copies instead. – berak Jun 12 '15 at 06:51
  • I don't intend to pass the the pointer to a function. Rather, I want an array of `cv::Mat` of the same length as channel numbers so that I can split and deal with them separately. Since I don't know how many channels an image has beforehand, I have to allocate the array like that. Maybe I should use `std::vector` instead, but I'm not sure whether I can pass an `std::vector` to `void merge(const Mat* mv, size_t count, OutputArray dst)` as the first parameter. – btshengsheng Jun 12 '15 at 13:03
  • please try either a plain `Mat[3]` or a `vector` with [this merge overload](http://docs.opencv.org/ref/master/d2/de8/group__core__array.html#ga61f2f2bde4a0a0154b2333ea504fab1d) – berak Jun 13 '15 at 04:46

1 Answers1

0

In C++ there is a significant difference between memory allocated with new and memory allocated with new [].

int* p = new int;
delete p;
p = new int[8];
delete p; // error/crash
delete [] p; // correct

The Ptr class is an RAII container for managing ownership of pointers. When you assign to it, it takes ownership of that allocation, meaning it will delete it when the Ptr goes out of scope (in this case at the end of the function).

It uses delete by default hence your crash, and the documentation suggests you will need to use the constructor that lets you specify you own deleter:

// see http://docs.opencv.org/master/d0/de7/structcv_1_1Ptr.html
void array_deleter(Mat* m)
{
    delete [] m;
}

Prt<Mat> ptr(new Mat[i], array_deleter);
kfsone
  • 23,617
  • 2
  • 42
  • 74
  • So does that mean whatever object `cv::Ptr` owns, the destructor will default to `DefaultDeleter`,which is actually a standard C++ `delete`? Also, why I can use `unique_ptr = new int[i]` but get `error: conversion from ‘cv::Mat*’ to non-scalar type ‘cv::Ptr’ requested` when I try `Ptr< Mat[] > ptr=new Mat[i]`. What's the difference? Is it because the conversion from `int*` to `int[]` is somehow defined, but `cv::Mat*` to `cv::Mat[]` is not? – btshengsheng Jun 12 '15 at 13:21
  • See http://stackoverflow.com/questions/16364637/conversion-to-non-scalar-type-with-std-c11-smart-pointer and http://en.cppreference.com/w/cpp/memory/unique_ptr/make_unique if you have c++14 – kfsone Jun 12 '15 at 15:08
  • Thank you very much for your help. For those confused about the difference between `std::unique_ptr SineUniform = new osg::Uniform( "Sine", 0.0f );` and `std::unique_ptr SineUniform(new osg::Uniform( "Sine", 0.0f ));` from the link kfsone provided as I did, I've found this post http://stackoverflow.com/questions/14081743/for-a-class-constructor-what-is-the-difference-between-the-assignment-via-paren – btshengsheng Jun 13 '15 at 05:19