C++ 编译引入错误

C++ Compilation introduce errors

本文关键字:错误 编译 C++      更新时间:2023-10-16

我在Visual Studio 2010中有一个多线程C++Windows项目,它使用Qt(5.1.1)和OpenCV(2.4.8)。当我在调试模式下构建它时,一切运行正常,但是当我在发布模式下构建它时,程序崩溃了。两种配置几乎相同(仅在版本中我有多线程 DLL/MD 和调试多线程调试 DLL/MDd),我禁用了版本的优化,甚至启用了调试以捕获错误。最奇怪的是,崩溃的同一段代码在另一个控制台项目中运行良好。

该错误是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

正如我在调试中所说,代码运行没有问题,findContours调用_contours.create(total, 1, 0, -1, true);(在 OpenCV 轮廓的第 1720 行.cpp)并继续使用该方法。但是在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();

它再次调用 againgkind()再次调用type()(而不是应有的kind()),进行无限递归循环,带来堆栈溢出

我尝试创建一个新的Visual Studio 2010项目,以查看这是否是项目创建问题,但问题仍然存在。

我的猜测是函数地址在发布模式下是错误的,所以当它尝试调用create()时,它会调用另一个地址,在堆栈中弄得一团糟,但这只是我的猜测。起初我会责怪 OpenCV 发布的 dll,但是,正如我所说,在另一个仅运行该特定代码的控制台项目中,代码在机器人构建模式下运行良好。我不明白我的其他线程和代码如何触发此行为,因为错误归结为 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 中所述。有谁知道这其中的含义以及它之间的关系?

我过去在混合 VC 运行时版本时遇到过类似的症状。如果您使用的是VC2010,而OpenCV 2.4.8是在2012年甚至2013年构建的,那么您的ABI不匹配。 例如,内存 std::vector 的布局不同,可能是 vtable 中某些方法的顺序发生了变化,等等。

测试这一点的一种简单方法是在调试时检查"模块"窗口并查找更高版本的运行时 dll。您的是msvcr100d.dll,如果您看到msvcr110d或120d - 这可能是来源。 (假设您和 OpenCV 都动态链接到 CRT - 我无法判断)。

调试和发布在内存分配方面是不同的。通常在调试模式下,分配更大。 可能是你滥用了一些openCV电话,但你没有意识到这一点。 我会做下一步行动:

  1. 验证帧是否正常。可能是太大,或者宽度或高度没有启动;

  2. 验证下一行之后图像变量是否正常

    垫子图像 = Mat(frame.height(), frame.width(), CV_8UC4, rame.scanLine(0));

  3. 第一个和第二个参数相同时,是否可以调用 cvtColor(可能是你在这里滥用了 CV)

  4. 第一个和第二个参数相同时调用高斯模糊可以吗?尝试放置不同的第二个参数

  5. 阈值函数调用也是如此

  6. 检查在 image.clone 调用后,countoursImage 是否为有效矩阵。

我猜:除了检查库本身是否正确之外,还要检查是否以相同的顺序(在所有构建中)指定所有库。否则,链接器可能会在最终链接器阶段将函数名称绑定到不同的实现。

我遇到了同样的问题。我正在使用Qt 5.1.1和opencv248,我的应用程序在从findcontours返回后崩溃。事实证明,我在pro文件中使用了vc10库和相应的dll,而正在使用的Qt编译器是msvc2013。切换到opencv 12中的vc248文件夹为我解决了这个问题。

您是否检查过 opencv 库的发布版本。 Opencv 为发布版和调试版提供了不同的库集。如果您已允许在发布模式下包含调试库。您的代码将编译时没有错误,但在执行时会抛出 excecption。 检查您的库 转到

Project->Properties->Configuration Properties->linker->Input->Additional Dependencies.

确保发布模式中没有一个 Opencv 库以"d"结尾。

发布库:"opencv_core248.lib">

用于调试的库:"opencv_core248d.lib">

请注意调试模式末尾的D

我希望这会有所帮助。