2009-12-31 7 views
3

Je reçois ce eror de Visual C++:erreur de corruption de tas étrange

HEAP [ShockRay3.exe]: bloc Heap à 00.557.018 modifié à 00.557.044 passé taille demandée de 24

Cela se produit lorsque j'ajoute une ligne de code entre deux appels récursifs dans une fonction. Toute la ligne de code change un pointeur mais pour une raison quelconque, chaque fois que je le mets, j'obtiens cette erreur.

Ceci est une version simplifiée du code (seulement stuff mémoire tas un des appels de fonction)

int KDTree::BuildBranch(int height, Mailbox** objs, int nObjects) 
{ 
    {...} 
     //Check for termination 
    if(height == -1 || nObjects < minObjectsPerNode) 
    { 
     {...} 

     return nodeIndex - 1; 
    } 

    //Save this node's index and increment the current index to save space for this node 
    BoundingBox* tempBox = new BoundingBox(); 
    //If this is first voxel, we don't keep track of stradle counts 
    if(nodeIndex == 1) 
    { 
     {...} 

     for(int i = 0; i < nObjects; i++) 
     { 
      //Get bounding box 
      objs[i]->prim->MakeBoundingBox(tempBox); 

      //Add mins to split lists 
      xMins[index] = tempBox->x0; 
      yMins[index] = tempBox->y0; 
      zMins[index] = tempBox->z0; 

      //Add maxs 
      xMaxs[index] = tempBox->x1; 
      yMaxs[index] = tempBox->y1; 
      zMaxs[index] = tempBox->z1; 
      index++; 
     } 
    } 
    else 
    { 
     for(int i = 0; i < nObjects; i++) 
     { 
      //Get bounding box 
      objs[i]->prim->MakeBoundingBox(tempBox); 

      //Add mins to split lists checking for straddle 
      if(tempBox->x0 < curVoxelBounds->x0) 
      { 
       {...} 
      } 
      else 
      { 
       xMins[xMinCount] = tempBox->x0; 
       {...} 
      } 

      if(tempBox->y0 < curVoxelBounds->y0) 
      { 
       {...} 
      } 
      else 
      { 
       yMins[yMinCount] = tempBox->y0; 
       {...} 
      } 

      if(tempBox->z0 < curVoxelBounds->z0) 
      { 
       {...} 
      } 
      else 
      { 
       zMins[zMinCount] = tempBox->z0; 
       {...} 
      } 

      //Add maxs to split lists checking for straddle 
      if(tempBox->x1 > curVoxelBounds->x1) 
      { 
       {...} 
      } 
      else 
      { 
       xMaxs[xMaxCount] = tempBox->x1; 
       {...} 
      } 

      if(tempBox->y1 > curVoxelBounds->y1) 
      { 
       {...} 
      } 
      else 
      { 
       yMaxs[yMaxCount] = tempBox->y1; 
       {...} 
      } 

      if(tempBox->z1 > curVoxelBounds->z1) 
      { 
       {...} 
      } 
      else 
      {   
       zMaxs[zMaxCount] = tempBox->z1; 
       {...} 
      } 
     } 
    } 

    //If this is the root node, construct the scene bounding box 
    if(nodeIndex == 1) 
    { 
     bb = new BoundingBox(xMins[0], xMaxs[nObjects - 1], yMins[0], yMaxs[nObjects - 1], zMins[0], zMaxs[nObjects - 1]); 
     curVoxelBounds = new BoundingBox(xMins[0], xMaxs[nObjects - 1], yMins[0], yMaxs[nObjects - 1], zMins[0], zMaxs[nObjects - 1]); 
    } 

    {...} 

    //Allocate space for left and right lists 
    Mailbox** leftList = new Mailbox*[minLeftCounter]; 
    Mailbox** rightList = new Mailbox*[minRightCounter]; 

    //Sort objects into lists of those to the left and right of the split plane 
    //Bounding box for left and right 
    BoundingBox* rightBox = NULL; 
    BoundingBox* leftBox = NULL; 
    //Saved pointer to current bounding box 
    BoundingBox* savedBox = curVoxelBounds; 

    int leftIndex = 0, rightIndex = 0; 
    {...} 
    switch(axis) 
    { 
    case 0: 
     for(int i = 0; i < nObjects; i++) 
     { 
      //Get object bounding box 
      objs[i]->prim->MakeBoundingBox(tempBox); 

      //Add to left and right lists when necessary 
      if(tempBox->x0 < splitLoc) 
      { 
       {...} 
      } 

      if(tempBox->x1 > splitLoc) 
      { 
       {...} 
      } 
     } 

     //Construct new bounding boxes 
     leftBox = new BoundingBox(curVoxelBounds->x0, splitLoc, curVoxelBounds->y0, 
      curVoxelBounds->y1, curVoxelBounds->z0, curVoxelBounds->z1); 
     rightBox = new BoundingBox(splitLoc, curVoxelBounds->x1, curVoxelBounds->y0, 
      curVoxelBounds->y1, curVoxelBounds->z0, curVoxelBounds->z1); 
     break; 

    case 1: 
     for(int i = 0; i < nObjects; i++) 
     { 
      //Get object bounding box 
      objs[i]->prim->MakeBoundingBox(tempBox); 

      //Add to left and right lists when necessary 
      if(tempBox->y0 < splitLoc) 
      { 
       {...} 
      } 

      if(tempBox->y1 > splitLoc) 
      { 
       {...} 
      } 

     } 

     //Construct new bounding boxes 
     leftBox = new BoundingBox(curVoxelBounds->x0, curVoxelBounds->x1, curVoxelBounds->y0, 
      splitLoc, curVoxelBounds->z0, curVoxelBounds->z1); 
     rightBox = new BoundingBox(curVoxelBounds->x0, curVoxelBounds->x1, splitLoc, 
      curVoxelBounds->y1, curVoxelBounds->z0, curVoxelBounds->z1); 
     break; 

    case 2: 
     for(int i = 0; i < nObjects; i++) 
     { 
      //Get object bounding box 
      objs[i]->prim->MakeBoundingBox(tempBox); 

      //Add to left and right lists when necessary 
      if(tempBox->z0 < splitLoc) 
      { 
       {...} 
      } 

      if(tempBox->z1 > splitLoc) 
      { 
       {...} 
      } 

     } 

     //Construct new bounding boxes 
     leftBox = new BoundingBox(curVoxelBounds->x0, curVoxelBounds->x1, curVoxelBounds->y0, 
      curVoxelBounds->y1, curVoxelBounds->z0, splitLoc); 
     rightBox = new BoundingBox(curVoxelBounds->x0, curVoxelBounds->x1, curVoxelBounds->y0, 
      curVoxelBounds->y1, splitLoc, curVoxelBounds->z1); 
     break; 
    }; 

    //Delete the bounding box 
    delete tempBox; 

    //Delete old objects array 
    delete[] objs; 

    {...} 

    //Change bounding box 
    curVoxelBounds = leftBox; 
    //Build the left branch 
    BuildBranch(height - 1, leftList, leftCount); 

    //Change bounding box 
    curVoxelBounds = rightBox; //<----THIS IS THE LINE RESULTING IN THE ERROR 
    //Build the right branch 
    int rcNodeIndex = BuildBranch(height - 1, rightList, rightCount); 

    //Restore bounding box 
    curVoxelBounds = savedBox; 

    //Delete left and right bounding boxes 
    delete leftBox; 
    delete rightBox; 

    {...} 

    return thisNodeIndex; 
} 

Si je prends cette ligne où je change le pointeur, le programme fonctionne. Si je le laisse dans, il ne fonctionne pas et la pile d'appels montre cette ligne:

delete[] objs; 

mais avant que la pile d'appel est la ligne qui semble être la cause. Je ne sais pas comment changer un pointeur peut sauter le code à cette ligne de suppression.

+0

La modification du pointeur ne saute nulle part. Immédiatement après avoir changé le pointeur, vous faites un appel récursif à la même fonction, qui se bloque. C'est pourquoi vous voyez cette ligne au-dessus du crash dans la pile des appels, comme il se doit. – AnT

+2

En ce qui concerne le crash, la fonctionnalité de votre code dépend de la valeur actuelle 'curVoxelBounds'. Votre implémentation contient un bogue (dépassement de la matrice, très probablement), qui ne se révèle que lorsque vous modifiez ce pointeur. C'est tout ce qu'il y a à faire. – AnT

+0

Je ne sais toujours pas pourquoi cela provoquerait un dépassement de la matrice. – Stewart

Répondre

2

Je ne vois rien de manifestement faux dans le code que vous avez posté, cependant une partie du code omis peut être pertinente. Alors, voici quelques idées pour enquêter sur:

  • sont-leftCount et rightCount étant calculé correctement afin qu'ils ne dépassent pas leurs listes?
  • Est-ce que leftList et rightList sont correctement remplis avec des pointeurs valides?
  • Lorsque le BuildBranch est appelé du monde extérieur, les deuxième et troisième paramètres sont-ils valides et corrects?
  • Et le monde extérieur s'attend-il à ce que le deuxième paramètre soit supprimé par cette fonction?

Si ces idées ne vous obtenez nulle part, puis quelques questions:

  • Combien de fois la fonction récursifs en lui-même lorsque l'accident se produit? Cela se passe-t-il au début ou au plus profond?
  • Est-il possible de réorganiser les appels récursifs afin que la boîte de droite soit traitée d'abord, puis la boîte de gauche après? Si oui, quel est le crash qui se produit lorsque vous essayez cela?
+0

Ouais, je suis sûr que c'est quelque part dans le code omis. Merci – Stewart

2

La chasse aux insectes peut prendre des jours (et des nuits!). Dans un si gros morceau de code, ce n'est pas facile à trouver, et ce que vous avez publié en lui-même n'a pas de bugs. Nous ne publierons pas non plus toute l'aide du code, car sans le reste de la classe, nous devrons le réimplémenter pour bien le tester.

Cependant, ce que je peux faire est de vous donner quelques indications:

  1. Réduisez votre échantillon de plantage au minimum - dans votre cas, charger les données les moins à l'KDTree qui fait planter.
  2. Pointeurs NULL après utilisation - au moins à des fins de test.
  3. Utiliser des assertions - Affirmer not-null avant chaque déréférencement de pointeur.
  4. Apprenez à utiliser votre compilateurs débogueur, et faire une étape par étape passthrough à travers l'exemple de taille minimale, en particulier d'examiner de près à curVoxelBounds
+0

Je suis d'accord, utilisez le débogueur. Visual Studio en a un excellent. C'est un genre de chose particulièrement difficile à déboguer, mais peut-être que si vous marchez un peu, vous attraperez des affaires amusantes – Mongoose

0

Vous pouvez essayer Application Verifier. Il est très bon pour trouver des écrasements de mémoire et des problèmes connexes.

Voici quelques informations importantes concernant le vérificateur d'application. Vous pouvez définir la validation full page heap. Si votre application est surchargée ou non, elle sera immédiatement interceptée. Et c'est extrêmement facile à utiliser. Et libre.