C++ 使用SetData()分配数据后cvReleaseImage()上的分段错误

C++ 使用SetData()分配数据后cvReleaseImage()上的分段错误,c++,opencv,C++,Opencv,我试图从相机中获取单个图像,对它们进行一些处理并释放使用的内存。我已经用类似于下面代码的代码做了相当长的一段时间: char* img_data = new char[ len ]; // I retrieve len from the camera. // Grab the actual image from the camera: // It fills the previous buffer with the image data. // It gives width and heig

我试图从相机中获取单个图像,对它们进行一些处理并释放使用的内存。我已经用类似于下面代码的代码做了相当长的一段时间:

char* img_data = new char[ len ]; // I retrieve len from the camera.

// Grab the actual image from the camera: 
// It fills the previous buffer with the image data.
// It gives width and height.

CvSize size;
size.width = width;
size.height = height;
IplImage* img = cvCreateImageHeader( size, 8, 1 );
img->imageData = img_data;

// Do the processing

cvReleaseImage( &img );
这段代码运行良好。我最近在imageData描述中读到,我不应该直接将数据分配给img->imageData,而是使用SetData,如下所示:

cvSetData( img, img_data, width );
然而,当我这样做时,我在cvReleaseImage调用中遇到了一个分割错误

我做错了什么

多谢各位

编辑:我尝试编译并运行@karlphillip建议的程序,我确实使用cvSetData遇到了分段错误,但直接分配数据时运行良好。
我正在使用Debian 6和OpenCV 2.3.1
char* img_data = (char*) malloc(len * sizeof(char)); 
// casting the return of malloc might not be necessary 
// if you are using a C++ compiler
编辑:由于OP的评论仍在崩溃

您没有向我们展示的其他内容正在使您的应用程序崩溃!我郑重建议您编写一个完整/最小的应用程序,以再现您遇到的问题

以下应用程序在使用OpenCV 2.3.1的Mac OS X中运行良好

#include <cv.h>
#include <highgui.h>


int main()
{
    char* img_data = (char*) malloc(625); 

    CvSize size;
    size.width = 25;
    size.height = 25;
    IplImage* img = cvCreateImageHeader( size, 8, 1 );

    //img->imageData = img_data;
    cvSetData( img, img_data, size.width );

    cvReleaseImage( &img );

    return 0;
}

问题是,你使用新的C++内存分配方法,同时使用OpenCV的C接口,试图用自由的内部CVRelaseIn图像释放内存块。C和C++的内存分配不能混合在一起。 解决方案:使用malloc分配内存:

char* img_data = (char*) malloc(len * sizeof(char)); 
// casting the return of malloc might not be necessary 
// if you are using a C++ compiler
编辑:由于OP的评论仍在崩溃

您没有向我们展示的其他内容正在使您的应用程序崩溃!我郑重建议您编写一个完整/最小的应用程序,以再现您遇到的问题

以下应用程序在使用OpenCV 2.3.1的Mac OS X中运行良好

#include <cv.h>
#include <highgui.h>


int main()
{
    char* img_data = (char*) malloc(625); 

    CvSize size;
    size.width = 25;
    size.height = 25;
    IplImage* img = cvCreateImageHeader( size, 8, 1 );

    //img->imageData = img_data;
    cvSetData( img, img_data, size.width );

    cvReleaseImage( &img );

    return 0;
}

我也有这个问题,但我相信从我收集的信息来看,它已经解决了 ; 即使用cvReleaseImageHeader而不是cvReleaseImageHeader

例如:

unsigned int width = 100;
unsigned int height = 100;
unsigned int channels = 1;
unsigned char* imageData = (unsigned char*)malloc(width*height*channels);
// set up the image data

IplImage *img = cvCreateImageHeader(cvSize(width, height), IPL_DEPTH_8U, channels);
cvSetData(img, imageData, width*channels); 

// use img

cvReleaseImageHeader(&img);

// free(imageData) when finished

我也有这个问题,但我相信从我收集的信息来看,它已经解决了 ; 即使用cvReleaseImageHeader而不是cvReleaseImageHeader

例如:

unsigned int width = 100;
unsigned int height = 100;
unsigned int channels = 1;
unsigned char* imageData = (unsigned char*)malloc(width*height*channels);
// set up the image data

IplImage *img = cvCreateImageHeader(cvSize(width, height), IPL_DEPTH_8U, channels);
cvSetData(img, imageData, width*channels); 

// use img

cvReleaseImageHeader(&img);

// free(imageData) when finished

我想为这次讨论添加一个细节。这里面似乎有某种缺陷 cvReleaseHeader函数。 您必须先释放标题,然后释放图像数据。
如果您以另一种方式进行操作,即释放图像数据,然后调用cvReleaseHeader函数,那么它将以欺骗的方式工作。但是它会在内部泄漏内存,过了一段时间,您的应用程序就会崩溃。

我想在这个讨论中添加一个细节。这里面似乎有某种缺陷 cvReleaseHeader函数。 您必须先释放标题,然后释放图像数据。
如果您以另一种方式进行操作,即释放图像数据,然后调用cvReleaseHeader函数,那么它将以欺骗的方式工作。但是它会在内部泄漏内存,过了一段时间,您的应用程序就会崩溃。

通常,如果您手动分配头并设置数据,您应该只释放头并自己释放数据:

// allocate img_data

IplImage* img = cvCreateImageHeader( size, 8, 1 );
img->imageData = img_data;
cvReleaseImageHeader( &img ); // frees only the header

// free img_data
如果您调用cvReleaseImage,它也会尝试释放数据,因此您随后依赖OpenCV实现来完成此操作,但在您的案例中失败了,因为它使用free,而您分配了彼此不兼容的new。
另一个选项是使用malloc分配并调用cvReleaseImage。

通常,如果您手动分配标头并设置数据,则应仅取消分配标头并自行释放数据:

// allocate img_data

IplImage* img = cvCreateImageHeader( size, 8, 1 );
img->imageData = img_data;
cvReleaseImageHeader( &img ); // frees only the header

// free img_data
如果您调用cvReleaseImage,它也会尝试释放数据,因此您随后依赖OpenCV实现来完成此操作,但在您的案例中失败了,因为它使用free,而您分配了彼此不兼容的new。
另一个选项是使用malloc进行分配并调用cvReleaseImage。

你说得对。我应该使用OpenCV的C++接口,真的:但是,这并没有解决分段错误。它并没有解决崩溃问题,因为应用程序中有其他代码导致了它,而您没有与我们共享它。我更新了答案,向您展示了它的工作原理,我们无法进一步帮助您,除非您编写一个可编译的最小应用程序来复制您正在观察的行为。我正要尝试编写一个像您建议的那样的小程序,看看它是否工作。一旦我访问了同一台机器,我将用结果更新问题。非常感谢。您发布的可编译最小应用程序也会崩溃。这可能是OpenCV 2.3.1 Linux版中的一个bug吗?很有趣。我刚刚在我的软呢帽盒上测试了这个代码,它崩溃了。这可能是一个OpenCV错误。我建议你向OpenCV邮件列表发送一封电子邮件,并与他们分享这个问题。你是对的。我应该使用OpenCV的C++接口,真的:T
但是,他的没有解决分段错误。它没有解决崩溃问题,因为您的应用程序中有其他代码导致了崩溃,而您没有与我们共享。我更新了答案,向您展示了它的工作原理,我们无法进一步帮助您,除非您编写一个可编译的最小应用程序来复制您正在观察的行为。我正要尝试编写一个像您建议的那样的小程序,看看它是否工作。一旦我访问了同一台机器,我将用结果更新问题。非常感谢。您发布的可编译最小应用程序也会崩溃。这可能是OpenCV 2.3.1 Linux版中的一个bug吗?很有趣。我刚刚在我的软呢帽盒上测试了这个代码,它崩溃了。这可能是一个OpenCV错误。我建议你发一封电子邮件到OpenCV邮件列表,并与他们分享这个问题。很好!这解决了问题,但cvReleaseImage在GNU/Linux上失败,而不是在Mac OS X上失败,这仍然很奇怪。我在OpenCV邮件列表上发送了一封电子邮件,但没有被接受,可能我无法发布到外部网站或其他东西的链接。无论如何,非常感谢!是的,在OpenCV 3.1.0中,它在macOS Sierra上工作,但现在我将应用程序移植到Windows Cygwin环境中,它会因隔离故障而崩溃!在Cygiwn上使用CVReleaseMageHeader,我仍然有这样的错误openCV错误:cvarrToMat中的参数未知数组类型错误,文件C:\openCV\sources\modules\core\src\matrix.cpp,第893行很好!这解决了问题,但cvReleaseImage在GNU/Linux上失败,而不是在Mac OS X上失败,这仍然很奇怪。我在OpenCV邮件列表上发送了一封电子邮件,但没有被接受,可能我无法发布到外部网站或其他东西的链接。无论如何,非常感谢!是的,在OpenCV 3.1.0中,它在macOS Sierra上工作,但现在我将应用程序移植到Windows Cygwin环境中,它会因隔离故障而崩溃!在Cygiwn上使用CVReleaseMageHeader,我仍然有这样的错误openCV错误:cvarrToMat中的参数未知数组类型错误,文件C:\openCV\sources\modules\core\src\matrix.cpp,第893行