【发布时间】:2014-03-26 17:57:26
【问题描述】:
我在 Visual Studio 2010 中有一个使用 Qt (5.1.1) 和 OpenCV (2.4.8) 的多线程 C++ windows 项目。当我在 Debug 模式下构建它时,一切运行正常,但是当我在 Release 模式下构建它时,程序崩溃了。两种配置几乎相同(只是在 Release 中我有 Multi-threaded DLL /MD 和在 Debug Multi-threaded Debug DLL /MDd 中),我禁用了 Release 的优化,甚至启用了调试以捕获错误。最奇怪的是,同一段代码崩溃了,在另一个控制台项目中运行得很好。
错误是OpenCV代码内部的,与我的代码无关,我的代码只是:
void MyProject::findEllipses(QImage &frame, vector<RotatedRect> &ellipses)
{
Mat image = Mat(frame.height(), frame.width(), CV_8UC4, frame.scanLine(0));
cvtColor(image, image, CV_RGB2GRAY);
GaussianBlur(image, image, Size(3, 3), 0, 0, 4);
threshold(image, image, treshVal, 255, THRESH_BINARY);
vector<vector<Point> > contours;
Mat contoursImage = image.clone();
findContours(contoursImage, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE, Point(0, 0));
// ....Mode Code
正如我在 Debug 中所说,代码运行没有问题,findContours 调用 _contours.create(total, 1, 0, -1, true);(在 OpenCV 的 contours.cpp 的第 1720 行)并继续使用该方法....但是在Release,当我进入_contours.create(total, 1, 0, -1, true) 时,程序没有执行该方法,而是跳转到void _OutputArray::clear() const(matrix.cpp 的第1674 行)并被困在那里,因为它调用int k = kind();在它的第一行,而不是调用cv::kind(),调用:
int _InputArray::type(int i) const
{
int k = kind();
再次调用kind() 再次调用type()(而不是应有的kind()),进行无限递归循环,带来堆栈溢出。
我尝试创建一个新的 Visual Studio 2010 项目以查看这是否是项目创建问题,但问题仍然存在。
我的猜测是函数地址在发布模式下是错误的,所以当它尝试调用 create() 时,它会调用另一个地址,从而在堆栈中造成混乱,但这只是我的猜测。起初我会责怪 OpenCV 发布 dll,但是,正如我所说,在另一个只运行该特定代码的控制台项目中,代码在 bot 构建模式下运行良好。我看不到我的其他线程和代码如何触发此行为,因为错误归结为 OpenCV 中的错误函数调用。
这超出了我的知识范围,我不知道如何解决这个问题,我感谢我能在这个问题上获得的所有帮助,因为我已经用尽了所有的想法来解决它......
编辑:
我做了一个小项目,这样任何人都可以看到正在发生的事情。
文件位于: https://app.box.com/s/3owljl44emv57erinrf8
为了运行它,您必须拥有 OpenCV 2.4.8 和 Qt 5.1.1 并配置 Visual Studio 2010 项目以从正确的位置获取包含文件。在资源文件夹中有一个要加载的图像,在 SaraVisualControl.cpp 第 20 行中,您必须放置图像的正确路径,抱歉我没有自动设置,但我急于打包一个小项目。有关如何运行它的任何其他问题,请告诉我。
编辑 2
我发现了这个旧线程:http://code.opencv.org/issues/2218 用户似乎遇到了与我相同的问题,并且仅在关闭 OPENCV_CAN_BREAK_BINARY_COMPATIBILITY 的情况下运行 CMake 似乎可以解决它。但是这个选项不再出现在新版本的 OpenCV 中,如http://code.opencv.org/issues/2358 所述。有谁知道这意味着什么以及它可能是如何相关的?
【问题讨论】:
-
使用调试器,在你的代码中设置一个断点,在那里你调用崩溃的函数,检查输入 - 它是否都有效,所有输入指针是否都实际指向对象等等。你是可能在某处调用未定义的行为。
-
嗯,这正是我如何捕捉到该错误...我用断点检查了它,并进入了函数...在调试模式下它会在它应该执行的位置...在发布它不会。 ..就这么简单:) 是的,所有输入都是有效的
-
最简单的修复方法可能是在您的项目中包含 OpenCV 源代码(否则确保编译器开关匹配)
-
确保您的调试器中显示的堆栈跟踪是正常的,并且实际显示正在发生的事情,因为在发布模式下通常无法信任调试器。
-
@DieterLücking 我自己重新编译了 OpenCV 以获得 dll 的 .pdb,这样我就可以进入 OpenCV 函数
标签: c++ visual-studio-2010 qt opencv