OpenARK-SDK.exe 中 0x00007FF74F27A526 处的未处理异常:0xC00000FD:堆栈溢出(参数:0x0000000000000001、0x000000EEC5803FD
Posted
技术标签:
【中文标题】OpenARK-SDK.exe 中 0x00007FF74F27A526 处的未处理异常:0xC00000FD:堆栈溢出(参数:0x0000000000000001、0x000000EEC5803FD8)【英文标题】:Unhandled exception at 0x00007FF74F27A526 in OpenARK-SDK.exe: 0xC00000FD: Stack overflow (parameters: 0x0000000000000001, 0x000000EEC5803FD8) 【发布时间】:2017-06-01 03:41:35 【问题描述】:以下代码 sn-p 导致 ***。
Unhandled exception at 0x00007FF74F27A526 in OpenARK-SDK.exe: 0xC00000FD: Stack overflow (parameters: 0x0000000000000001, 0x000000EEC5803FD8).
我该如何解决?它是我参与的open-source repository 的一部分,我希望不要在这里进行重大更改:
/***
Recursively performs floodfill on depthMap
***/
void DepthCamera::floodFill(int x, int y, cv::Mat& depthMap, cv::Mat& mask, double max_distance)
if (x < 0 || x >= depthMap.cols || y < 0 || y >= depthMap.rows || depthMap.at<cv::Vec3f>(y, x)[2] == 0.0)
return;
if (closeEnough(x, y, depthMap, 4, max_distance))
mask.at<cv::Vec3f>(y, x) = depthMap.at<cv::Vec3f>(y, x);
depthMap.at<cv::Vec3f>(y, x)[0] = 0;
depthMap.at<cv::Vec3f>(y, x)[1] = 0;
depthMap.at<cv::Vec3f>(y, x)[2] = 0;
else
return;
floodFill(x + 1, y, depthMap, mask, max_distance);
floodFill(x - 1, y, depthMap, mask, max_distance);
floodFill(x, y + 1, depthMap, mask, max_distance);
floodFill(x, y - 1, depthMap, mask, max_distance);
/***
Check whether candidate point is close enough to neighboring points
***/
bool DepthCamera::closeEnough(int x, int y, cv::Mat& depthMap, int num_neighbors, double max_distance)
int num_close = 0;
if (x - 1 < 0 || depthMap.at<cv::Vec3f>(y, x - 1)[2] == 0 || Util::euclidianDistance3D(depthMap.at<cv::Vec3f>(y, x), depthMap.at<cv::Vec3f>(y, x - 1)) < max_distance)
num_close++;
if (x + 1 >= depthMap.cols || depthMap.at<cv::Vec3f>(y, x + 1)[2] == 0 || Util::euclidianDistance3D(depthMap.at<cv::Vec3f>(y, x), depthMap.at<cv::Vec3f>(y, x + 1)) < max_distance)
num_close++;
if (y - 1 < 0 || depthMap.at<cv::Vec3f>(y - 1, x)[2] == 0 || Util::euclidianDistance3D(depthMap.at<cv::Vec3f>(y, x), depthMap.at<cv::Vec3f>(y - 1, x)) < max_distance)
num_close++;
if (y + 1 >= depthMap.rows || depthMap.at<cv::Vec3f>(y + 1, x)[2] == 0 || Util::euclidianDistance3D(depthMap.at<cv::Vec3f>(y, x), depthMap.at<cv::Vec3f>(y + 1, x)) < max_distance)
num_close++;
if (num_close >= num_neighbors)
return true;
return false;
和
double Util::euclidianDistance3D(cv::Vec3f pt1, cv::Vec3f pt2)
double dx = pt1[0] - pt2[0];
double dy = pt1[1] - pt2[1];
double dz = pt1[2] - pt2[2];
return sqrtf(dx*dx + dy*dy + dz*dz);
调用者:
void DepthCamera::computeClusters(double max_distance, double min_size)
clusters.clear();
cv::Mat depthMap = cv::Mat::zeros(depthMap.rows, depthMap.cols, depthMap.type());
cv::medianBlur(xyzMap, depthMap, 3);
cv::Mat mask = cv::Mat::zeros(depthMap.rows, depthMap.cols, depthMap.type());
for (int r = depthMap.rows - 1; r >= 0; r--)
for (int c = 0; c < depthMap.cols; c++)
if (depthMap.at<cv::Vec3f>(r, c)[2] > 0.2)
mask = cv::Mat::zeros(depthMap.rows, depthMap.cols, depthMap.type());
floodFill(c, r, depthMap, mask, max_distance);
cv::Mat channels[3];
cv::split(mask, channels);
if (cv::countNonZero(channels[2]) > min_size)
cv::medianBlur(mask, mask, 3);
clusters.push_back(mask.clone());
如果需要更多信息,请告诉我。基本上,当我靠近相机时,就会发生 *** 异常。
这是调用堆栈的屏幕截图:
这是我的一个screencast run without debugging
。
【问题讨论】:
你能看一下堆栈跟踪吗?堆栈溢出通常是过度递归或过度分配。一层一层往上看,看看那些看起来不对的变量。 @MonaJalal -- 很明显,您正在一遍又一遍地调用函数,一遍又一遍,一遍又一遍,等等,再次导致堆栈溢出。你的递归没有结束,你需要弄清楚为什么你的逻辑永远不会展开。 不,它告诉您递归的结束条件不完整或不正确。这可能由任何相机触发,具体取决于错误或设计缺陷。 您需要了解更多如何使用调试器,并且您(而不是我们)应该修复您的错误。堆栈溢出错误和无限递归很容易修复。 您正在使用使用大量堆栈的基本洪水填充算法。This Wikipedia article 处理此问题。 【参考方案1】:递归的结束条件不完整或不正确。
如果您查看 Floodfill,会返回两种情况,一种触发递归。这告诉我们递归块不正确。具体来说,closeEnough() 没有按预期工作,因为您触发了一个永远不会返回 true 的案例。
您将查看传递给 closeEnough 的变量,以了解为什么它们永远不会满足它。只看代码,我就知道堆栈溢出的情况永远不会如此:
if (num_close >= num_neighbors)
我可以猜测哪些条件没有得到满足,但您可以通过查看传递给 closeEnough 的值更轻松地做到这一点。
如果这还不够,请给我们数值。
【讨论】:
当我按F10逐行调试它并在computeCluster的开头放置一个断点,并靠近相机甚至在我靠近相机时开始调试时,异常从来没有发生过,这使得当我run without debugging
时很难确定是什么值导致了异常
你的调试器是什么?在 Visual Studio 中,您可以只运行调试版本,等待它崩溃,然后在它崩溃后,您仍然可以查看堆栈的每个级别的变量。如果这不可能,您可以使用构建标志将每次调用 closeEnough(带有值)写入日志文件,这样您就可以在崩溃时以这种方式查看值。
在 Visual Studio + Windows 中,还可以为发布版本打开完整的故障转储。通过故障转储 + PDB 文件 + 源,您可以再次查看堆栈框架上调用的变量值。
如果您在没有调试的情况下运行:当崩溃发生时,如果您显示有关崩溃的详细信息,Windows 是否会为您提供“调试应用程序”的机会? (以“点击重试调试应用程序”为例)
如果没有,请登录到文件或阅读故障转储:msdn.microsoft.com/en-us/library/windows/desktop/…【参考方案2】:
虽然我认为这不是解决问题的最佳方法,但至少在我的情况下这是一个解决方法。
欢迎分享其他答案。
【讨论】:
真正的解决方法是迭代地而不是递归地编写代码。 @MichealWalz 在他的 cmets 中指出了这一点。如果您发现 2,000,000 字节的堆栈不够用怎么办?再增加一次? 我考虑使用本机 OpenCV 洪水填充算法并感谢您的反馈和链接。 docs.opencv.org/trunk/d5/d26/ffilldemo_8cpp-example.html以上是关于OpenARK-SDK.exe 中 0x00007FF74F27A526 处的未处理异常:0xC00000FD:堆栈溢出(参数:0x0000000000000001、0x000000EEC5803FD的主要内容,如果未能解决你的问题,请参考以下文章
Groovy闭包 Closure ( 闭包中调用 Groovy 脚本中的方法 | owner 与 delegate 区别 | 闭包中调用对象中的方法 )