尝试调试一些使用opencv库的c ++ 11代码,会在gdb中产生分段错误。
我正在使用linux中的gdb调试以下函数。
MatchedFeatures extract_best_features(vector<Mat> imgs)
{
MatchedFeatures result;
cv::Ptr<Feature2D> f2d = xfeatures2d::SIFT::create();
//cv::Ptr<Feature2D> f2d = xfeatures2d::SURF::create();
//cv::Ptr<Feature2D> f2d = ORB::create();
for (auto it = 0; it < imgs.size(); ++it) {
vector<KeyPoint> keyPoints;
Mat descriptors;
f2d->detect(imgs[it], keyPoints);
f2d->compute(imgs[it], keyPoints, descriptors);
result.imgFeatures.push_back(ImgFeatures{imgs[it], keyPoints, descriptors});
}
BFMatcher matcher;
vector< DMatch > matches;
matcher.match(result.imgFeatures[0].descriptors,
result.imgFeatures[1].descriptors,
matches);
cout << matches.size() << "\n";
//extract top 10
sort(matches.begin(), matches.end(),
[&](const DMatch x, const DMatch y) -> bool
{ return x.distance <= y.distance; });
result.matches = vector<DMatch>(matches.begin(),matches.begin()+5); // <- debug fails here and matches is empty in debug mode
return result;
}
当调试器到达我对matches
向量进行切片的点时,会产生分段错误。检查matches
变量并查看堆栈跟踪显示matches
为空。但是,只有在调试模式下为空。
当我正常运行时,代码完全正常,只有在调试时才会失败。
我注意到BFMatcher在执行匹配时产生了很多线程,因此我怀疑问题是由于线程而产生的。虽然我刚开始学习c ++,但我只能猜错了。
有没有办法“等待”线程在gdb中正确完成?
或者是否有其他一些技巧可以让我在c ++中调试和检查这种代码而不会产生分段错误和来自副作用生成程序的空结果,例如match
中的BFMatcher
?
编辑(解决了问题):
因此,当在cgdb中运行程序时使用文件路径作为参数时,应该使用完整的路径(而不是使用主文件夹快捷方式〜/)的可执行文件或路径的相对路径...我现在能够调试我的程序非常好..
答案 0 :(得分:1)
在调试器中运行时崩溃但在其他情况下不会崩溃的代码可能表示您使用了未初始化的数据并且缺少空指针检查。在调试器中运行时,调试器通常会清除程序使用的所有内存,包括本地变量。这意味着指针将是空指针,并且取消引用空指针通常会导致崩溃。
如果未在调试器中运行,则不会初始化局部变量,因此不存在空指针访问。另一方面,由于本地数据(未在调试器中运行时)未初始化,因此值 indeterminate ,并且使用未初始化的数据会导致未定义的行为。它可能似乎可以工作。
另一方面,如果不在调试器中运行时崩溃(或意外结果),但它在调试器内工作正常,那么使用未初始化的本地数据仍然存在相同的问题,但你做有空指针检查。
调试这类问题的最佳方法是使用内存调试器,例如Valgrind。
答案 1 :(得分:1)
一个问题可能与线程无关。是否使用线程存在问题。
问题在于:
//extract top 10
sort(matches.begin(), matches.end(),
[&](const DMatch x, const DMatch y) -> bool
{ return x.distance <= y.distance; }); // <-- Suspect
您的排序条件似乎不符合strict weak ordering。只要您将<=
视为“小于”标准,它几乎总是一个错误。 std::sort
需要严格弱的订单才能正常运作。
将行更改为:
{ return x.distance < y.distance; });
这是否完全解决了你的问题,我不能说。但 是您必须解决以进行测试的问题。
由于您使用的是gcc
,我只想提一下Visual Studio的调试运行时会检测到这样的问题。
它检测它的方式是通过两次调用您的排序标准。第一次使用一个订单中的参数,第二次使用参数进行交换。运行时比较两个结果,如果它们不遵循严格弱顺序,则运行时断言。对于您的情况,如果x.distance == y.distance
,那么调试运行时将立即断言。