我想从c ++代码返回一个Mat对象到Unity。但是,我在c ++部分得到访问冲突错误
Unity Editor [version: Unity 2017.3.0f3_a9f86dcd79df]
SaliencyCV.dll caused an Access Violation (0xc0000005)
in module SaliencyCV.dll at 0033:270027f0.
Error occurred at 2018-03-06_235212.
C:\Program Files\Unity\Editor\Unity.exe, run by Dilara.
43% memory in use.
16266 MB physical memory [9199 MB free].
18698 MB paging file [9861 MB free].
134217728 MB user address space [134185466 MB free].
Read from location 990d0000 caused an access violation.
这是c ++代码:
uchar* cppMethod(uchar* frameData, int WIDTH, int HEIGHT, int* rows, int* cols)
{
Mat img(HEIGHT, WIDTH, CV_8UC3);
img.data = frameData;
flip(img, img, 0);
Mat result = calculateSaliency(img);
*rows = result.rows;
*cols = result.cols;
int length = result.rows * result.cols * 3;
uchar* tmpArr = result.data;
uchar* resultArray = new uchar[length];
for (int i = 0; i < length; i++)
{
resultArray[i] = tmpArr[i];
}
return resultArray;
}
有人可以帮助我吗?
答案 0 :(得分:2)
您应该调用正确的Mat
构造函数which accepts external data pointer,以使对象不释放/破坏相应的内存位置data
指向。您可以在Mat::release()
中了解此行为。
您的代码存在的问题是
Mat img(HEIGHT, WIDTH, CV_8UC3)
分配一个大小为CV_8UC3
的{{1}}内存块,但未使用(因为您要将HEIGHT*WIDTH
成员变量更改为指向不同的内存位置,反正),data
被销毁,从而导致对img
的调用,而release()
则会导致frameData
, 预期的行为将前两行更改为
Mat img(HEIGHT, WIDTH, CV_8UC3, frameData);
如果您将resultArray
传递给C#,那么您很可能不管理指向内存的生命周期,那么您很可能会发生内存泄漏。 @Programmer在回答你之前的问题时已经建议你应该在C#中分配内存,将它传递给C ++,并在C ++端就地编写。
简而言之,你应该有类似的东西:
#include <algorithm>
void cppMethod(uchar *frameData, uchar *out, const int WIDTH, const int HEIGHT,
int *rows, int *cols) {
/* this constructor will not manage frameData's lifetime */
Mat img(HEIGHT, WIDTH, CV_8UC3, frameData);
/* in-place operation */
flip(img, img, 0);
/* local variable --- it will be destructed properly */
Mat result = calculateSaliency(img);
/* well-defined if rows and cols are scalars passed by reference */
*rows = result.rows;
*cols = result.cols;
/* make sure length will not overflow */
int length = result.rows * result.cols * 3;
/* you don't need this */
// uchar *tmpArr = result.data;
/* you sholuld NOT do this */
// uchar *resultArray = new uchar[length];
// use std::copy from <algorithm>
// for (int i = 0; i < length; i++) {
// resultArray[i] = tmpArr[i];
// }
std::copy(result.data, result.data + length, out);
// return resultArray;
}