gpt4 book ai didi

c++ - Release模式下的 OpenCV 堆损坏

转载 作者:太空宇宙 更新时间:2023-11-03 22:12:41 26 4
gpt4 key购买 nike

我在 Visual Studio 2010 中使用 openCV 2.4.10 编写了一个简单的代码,它从一些输入文件中提取了一些特征。

Mat extractSIFT(Mat img)
{
cv::Ptr<cv::FeatureDetector> detector;
cv::Ptr<cv::Feature2D> descriptorExtractor;

detector = cv::FeatureDetector::create("Dense");
descriptorExtractor = cv::DescriptorExtractor::create("SIFT");

detector->set("initXyStep",GRID_SPACING);

vector<cv::KeyPoint> keypoints;
detector->detect(img,keypoints);

Mat o;
//Mat o(keypoints.size(),128,CV_8U);
descriptorExtractor->compute(img,keypoints,o);

return o;
}

虽然这段代码在 Debug模式下工作正常(虽然速度很慢),但它给出了这个错误:

Windows has triggered a breakpoint in Prototype.exe.

This may be due to a corruption of the heap, which indicates a bug in Prototype.exe or any of the DLLs it has loaded.

This may also be due to the user pressing F12 while Prototype.exe has focus.

The output window may have more diagnostic information.

经过进一步调查,我发现输出变量 o 在 Release模式下看不到(悬停),但可以在简单的控制台转储上打印值。

在反汇编器中:

   848:     //Mat o(keypoints.size(),128,CV_8U);
849: descriptorExtractor->compute(img,keypoints,o);
850:
851: return o;
013F6FCF 56 push esi
013F6FD0 8D 55 C0 lea edx,[keypoints]
013F6FD3 52 push edx
013F6FD4 8D 45 0C lea eax,[img]
013F6FD7 50 push eax
013F6FD8 8B CF mov ecx,edi
013F6FDA C7 45 F0 01 00 00 00 mov dword ptr [ebp-10h],1
013F6FE1 E8 42 35 02 00 call cv::Feature2D::compute (141A528h)
013F6FE6 8B 45 C0 mov eax,dword ptr [keypoints]
013F6FE9 3B C3 cmp eax,ebx
013F6FEB 74 09 je extractSIFT4+306h (13F6FF6h)
013F6FED 50 push eax
**013F6FEE E8 EC 5C 02 00 call operator delete (141CCDFh)**
013F6FF3 83 C4 04 add esp,4

错误与星号一致。我尝试了几个项目属性(/Md、MT、增量构建...)重新编译了 openCV,检查了平台版本(v100)但无济于事。

最佳答案

对于任何类型的堆损坏,Microsoft Application Verifier(免费软件)都是非常宝贵的。您需要使用 Basics\Heaps 检查来配置它,我建议第一次禁用所有其他检查。保存设置后,您需要重新启动程序。它会恰好在损坏点崩溃。

例如:假设您在堆上分配了 100 个字节,然后尝试写入 101 个字节。在调试版本中,C++ CRT 将在 block 前后添加一些额外的填充,这将防止和检测小的堆损坏。在 Release 版本中,没有填充并且堆被损坏,而在其他一些堆操作的时刻,您通常知道得太晚了。使用 Application Verifier,您的程序将在写入第 101 个字节时恰好崩溃到调试器中。当它发生时,您可以在 Visual Studio 的输出窗口中看到一些额外的详细信息。

(注意:我始终为我开发的程序启用 Application Verifier with Basics\Heaps)

在这种特定情况下,您可能会看到 vector 的析构函数导致崩溃。这将意味着没有发生堆损坏,但程序正在尝试删除一个不存在的堆 block 。这很可能是由于链接了使用不同编译器或不同调试/发布设置编译的 OpenCV。 vector 类的结构和分配的 block 填充在编译器和 Debug/Release 之间有所不同。

更新:现在我们知道不同的 CRT 是这种情况,这里有一个扩展的解释。

  • vector 在 OpenCV 中分配并在您的程序中释放。
  • 如果您有不同版本的 CRT(编译器、调试/发布)
    • 分配和释放逻辑可以完全不同
    • 您的程序很可能会崩溃。
  • 如果你有相同版本的 CRT
    • CRT(C 运行时库)通过 Windows 堆处理内存分配。
    • 每个堆都有自己的句柄。
    • CRT(直到 VS2012 或类似的东西)将创建自己的分配堆。
    • 如果您有两个不同的 CRT,那么尝试释放由其他 CRT 分配的 block 将使用错误的堆句柄,这将导致崩溃或内存泄漏
    • 我想,您的程序在静态库中使用了 CRT,而 OpenCV 在 DLL 中使用了 CRT。
    • 静态链接 CRT 意味着嵌入私有(private) CRT。
    • 因此,您有两个 CRT:一个在您的程序中,一个在 OpenCV 使用的 DLL 中。
    • 现在您将程序更改为在 DLL 中使用 CRT,它们都使用相同的 DLL,每个进程只加载一次,因此您现在只有 CRT。

关于c++ - Release模式下的 OpenCV 堆损坏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30124620/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com