2017-06-01 53 views
-2

以下代碼片段導致stackoverflow。OpenARK-SDK.exe中的0x00007FF74F27A526未處理的異常:0xC00000FD:堆棧溢出(參數:0x0000000000000001,0x000000EEC5803FD8)

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()); 
       } 
      } 
     } 
    } 
} 

請讓我知道是否需要進一步的信息。基本上,當我靠近相機時,發生了stackoverflow異常。 enter image description here

這裏的調用堆棧的截圖: enter image description here

這裏是我的一個screencast試圖run without debugging它。

+2

你能看看堆棧跟蹤嗎?堆棧溢出通常是過度遞歸或過度分配。逐級上升,看看那些看起來不對的變量。 –

+0

@DaveS我添加了callstack的屏幕截圖。請看一看。 –

+3

@MonaJalal - 應該很明顯的是,你再次調用函數,一次又一次地重新執行,導致堆棧溢出。你的遞歸不會結束,你需要弄清楚爲什麼你的邏輯永遠不會放棄它。 – PaulMcKenzie

回答

0

雖然我認爲這不是最好的方法去做,但至少這是我的情況的一個修復。 enter image description here

隨時分享其他答案。

+3

然後,真正的修復是迭代地而不是遞歸地編寫代碼。 @MichealWalz在他的評論中指出了這一點。如果你發現200萬字節的堆棧不夠用會發生什麼?再次增加它? – PaulMcKenzie

+0

我想到了使用本機OpenCV floodfill算法並感謝反饋和鏈接。 http://docs.opencv.org/trunk/d5/d26/ffilldemo_8cpp-example.html –

3

遞歸的結束條件不完整或不正確。

如果你看看泛洪,兩個案例返回,一個觸發遞歸。這告訴我們遞歸塊不正確。具體來說,closeEnough()不能按預期工作,因爲您觸發了一個從不返回true的情況。

你會看到傳遞給close的變量來看看爲什麼他們永遠不會滿足它。只是看代碼,我可以告訴大家,這是從來沒有的情況如此,其中堆棧溢出:

if (num_close >= num_neighbors) { 

我可以猜測未得到滿足的條件,但你可以通過看這樣做更容易值被傳遞給closeEnough。

如果這還不夠,請給我們的價值。

+0

當我逐行調試F10,並在computeCluster的開頭放置一個斷點,並靠近相機,甚至在靠近相機時開始調試時,從不會發生異常,這使得它很難以確定什麼值導致異常,當我'沒有調試運行' –

+0

你的調試器是什麼?在Visual Studio中,您可以運行一個調試版本,等待它崩潰,然後在崩潰後,您仍然可以查看堆棧中每個級別的變量。如果這是不可能的,你可以有一個構建標誌來寫每個調用closeEnough(帶有值)到一個日誌文件,這樣你就可以在崩潰時看到這些值。 –

+0

在Visual Studio + Windows中,還可以爲發佈版本打開完整故障轉儲。使用故障轉儲+ PDB文件+源代碼,您可以再次查看堆棧幀中調用的變量值。 –