奇怪的堆损坏错误

时间:2009-12-31 03:17:05

标签: c++ c

我从Visual C ++中得到了这个错误:

HEAP [ShockRay3.exe]:堆积在00557018处修改为00557044过去请求的大小为24

当我在函数中的两个递归调用之间添加一行代码时会发生这种情况。所有代码行都改变了一个指针,但由于某些原因我每次都把它放进去,我得到了这个错误。

这是代码的简化版本(只有函数调用的堆内存)

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

如果我在更改指针的位置取出该行,程序将起作用。如果我保留它,它就不起作用,调用堆栈显示这一行:

delete[] objs;

但在此之前调用堆栈中的行似乎是导致此问题的。我不知道如何更改指针可以将代码跳转到该删除行。

3 个答案:

答案 0 :(得分:2)

我发布的代码中看不到任何明显错误,但是某些省略的代码可能是相关的。所以这里有一些想法要研究:

  • 是否正确计算了leftCountrightCount,以便它们不超过其列表?
  • leftListrightList是否正确填充了有效指针?
  • 从外界调用BuildBranch的地方,第二和第三个参数是否有效且正确?
  • 外界是否希望此功能删除第二个参数?

如果这些想法无法解决问题,那么请提出几个问题:

  • 崩溃发生时,该函数有多少次递归?它发生在开始还是深处?
  • 是否可以重新排序递归调用,以便先处理右框,然后再处理左框?如果是这样,当您尝试崩溃时会发生哪一次崩溃?

答案 1 :(得分:2)

虫子狩猎可能需要数天(和夜晚!)。在如此庞大的代码中,它并不容易找到,而且您发布的内容本身没有错误。也没有发布整个代码的帮助,因为没有其他课程,我们必须重新实现它来测试它。

但是,我能做的就是给你一些指示:

  1. 将崩溃的样本降至最低 - 在您的情况下,将最少的数据加载到使其崩溃的KDTree。
  2. 使用后的NULL指针 - 至少用于测试目的。
  3. 使用断言 - 在每个指针取消引用之前断言非空。
  4. 学习使用编译器调试器,并逐步完成最小尺寸示例,特别是仔细查看curVoxelBounds

答案 2 :(得分:0)

您可以尝试Application Verifier。它非常适合查找内存覆盖和相关问题。

以下是有关Application Verifier的一点重要信息。您可以设置full page heap验证。如果您的应用程序有任何堆超限或欠载,它将立即被捕获。而且它非常易于使用。而且免费。