2017-06-01 1 views
-2

L'extrait de code suivant provoque un stackoverflow.Exception non gérée à 0x00007FF74F27A526 dans OpenARK-SDK.exe: 0xC00000FD: dépassement de pile (paramètres: 0x0000000000000001, 0x000000EEC5803FD8)

Unhandled exception at 0x00007FF74F27A526 in OpenARK-SDK.exe: 0xC00000FD: Stack overflow (parameters: 0x0000000000000001, 0x000000EEC5803FD8). 

Comment puis-je résoudre ce problème? Il fait partie d'un open-source repository je contribue à et j'espère ne pas faire un changement majeur ici:

/*** 
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; 
} 

et

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

Il est appelé par:

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

S'il vous plaît laissez Je sais si d'autres informations sont nécessaires. Fondamentalement, quand je me rapproche de la caméra, l'exception stackoverflow se produit. enter image description here

Voici une capture d'écran du callstack: enter image description here

Voici un screencast de moi essayant de run without debugging il.

+2

Pouvez-vous regarder la trace de la pile? Un débordement de pile est souvent une récursivité excessive ou une allocation excessive. Montez niveau par niveau et regardez les variables pour celles qui semblent fausses. –

+0

@DaveS J'ai ajouté une capture d'écran de la pile d'appel. Jetez un coup d'oeil s'il vous plait. –

+3

@MonaJalal - Il aurait dû être évident que vous appeliez la fonction par-dessus, et au-dessus et au-dessus et au-dessus, etc. etc. à nouveau pour provoquer le débordement de la pile. Votre récursivité ne s'arrête pas, et vous devez comprendre pourquoi votre logique ne se déconnecte jamais. – PaulMcKenzie

Répondre

0

Bien que je ne pense pas que ce soit la meilleure façon d'y parvenir, au moins c'est une solution dans mon cas. enter image description here

N'hésitez pas à partager d'autres réponses.

+3

Le vrai correctif consiste alors à écrire le code de manière itérative au lieu de récursivement. Cela a été souligné par @MichealWalz dans ses commentaires. Que se passe-t-il si vous découvrez que 2 000 000 octets de pile ne suffisent pas? L'augmenter à nouveau? – PaulMcKenzie

+0

Je pense à l'utilisation de l'algorithme d'inondation OpenCV natif et merci pour les commentaires et le lien. http://docs.opencv.org/trunk/d5/d26/ffilldemo_8cpp-example.html –

3

Les conditions de fin de votre récursion sont incomplètes ou incorrectes.

Si vous observez l'inondation, deux cas reviennent et l'un déclenche la récursivité. Cela nous indique que le bloc récursif est incorrect. Plus précisément, closeEnough() ne fonctionne pas comme prévu puisque vous avez déclenché un cas qui ne renvoie jamais true.

Vous regardez les variables passées à closeEnough pour voir pourquoi elles ne le satisfont jamais. Il suffit de regarder le code, je peux dire que ce n'est jamais vrai pour le cas où la pile déborde:

if (num_close >= num_neighbors) { 

je pouvais deviner quelles conditions ne sont pas remplies, mais vous pouvez faire beaucoup plus facilement en regardant les valeurs étant passées à fermerEnough.

Si cela ne suffit pas, s'il vous plaît donnez-nous les valeurs.

+0

Quand je le débogue ligne par ligne disons par F10 et met un point d'arrêt au début de computeCluster, et approche de la caméra ou même débute le débogage quand je suis proche de la caméra, l'exception n'arrive jamais ce qui le rend si difficile pour comprendre quelle valeur provoque l'exception quand je 'coure sans débogage' –

+0

Quel est votre débogueur? Dans Visual Studio, vous pouvez simplement exécuter une version de débogage, attendre qu'elle se bloque, puis après l'arrêt, vous pouvez toujours regarder les variables pour chaque niveau de la pile. Si cela n'est pas possible, vous pouvez avoir un indicateur de construction pour écrire chaque appel à closeEnough (avec les valeurs) dans un fichier journal, de sorte que vous puissiez voir les valeurs au moment du crash de cette façon. –

+0

Dans Visual Studio + Windows, il est également possible d'activer les vidages sur incident complets pour les générations de versions. Avec le vidage sur incident + fichier PDB + source, vous pouvez à nouveau voir les valeurs des variables pour les appels sur le cadre de la pile. –