0

仅运行发布可执行文件时(通过 Visual Studio 运行时不会出现问题)我的程序崩溃。使用“附加到进程”功能时,Visual Studio 指示崩溃发生在以下功能中:

World::blockmap World::newBlankBlockmap(int sideLen, int h){
    cout << "newBlankBlockmap side: "<<std::to_string((long long)sideLen) << endl;
    cout << "newBlankBlockmap height: "<<std::to_string((long long)h) << endl;
    short*** bm = new short**[sideLen];
    for(int i=0;i<sideLen;i++){
        bm[i] = new short*[h];
        for(int j=0;j<h;j++){
            bm[i][j] = new short[sideLen];
            for (int k = 0; k < sideLen ; k++)
            {
                bm[i][j][k] = blocks->getAIR_BLOCK();
            }
        }
    }
    return (blockmap)bm;
}

从子类调用...

World::chunk* World_E::newChunkMap(World::floatmap north, World::floatmap east, World::floatmap south, World::floatmap west
,float lowlow, float highlow, float highhigh, float lowhigh, bool displaceSides){
    World::chunk* c = newChunk(World::CHUNK_SIZE+1,World::HEIGHT);

    for (int i = 0; i < World::CHUNK_SIZE ; i++)
    {
        for (int k = 0; k < World::CHUNK_SIZE ; k++)
        {
            c->bm[i][0][k] = blocks->getDUMMY_BLOCK();
        }
    }

    c->bm[(int)floor((float)(World::CHUNK_SIZE+1)/2.0f)-1][1][(int)floor((float)(World::CHUNK_SIZE+1)/2.0f)-1] = blocks->getSTONE_BLOCK();
    c->bm[(int)ceil((float)(World::CHUNK_SIZE+1)/2.0f)-1][1][(int)floor((float)(World::CHUNK_SIZE+1)/2.0f)-1] = blocks->getSTONE_BLOCK();
    c->bm[(int)floor((float)(World::CHUNK_SIZE+1)/2.0f)-1][1][(int)ceil((float)(World::CHUNK_SIZE+1)/2.0f)-1] = blocks->getSTONE_BLOCK();
    c->bm[(int)ceil((float)(World::CHUNK_SIZE+1)/2.0f)-1][1][(int)ceil((float)(World::CHUNK_SIZE+1)/2.0f)-1] = blocks->getSTONE_BLOCK();

    return c;

}

在哪里...

class World {
public: typedef short*** blockmap;
...

VS 指向的线是...

short*** bm = new short**[sideLen];

“附加到进程”函数统计局部变量是...... sideLen = 1911407648 h = 0 这是我没想到的,但 cout 分别输出 9 和 30,这是预期的。

我知道大多数“仅发布时崩溃”问题是由于未初始化的变量造成的,但是,我在这里看不到相关的。

我得到的唯一错误消息是... Windows 在 Blocks Project.exe 中触发了一个断点。这可能是由于堆损坏

我被这个问题难住了,错误是什么?我怎样才能更好地调试发布可执行文件?

如果需要,我可以发布更多代码,但是,请记住其中有很多。

提前谢谢你。

“而且我没有看到 World::newBlankBlockmap() 从第二块代码中调用。-迈克尔伯尔”,我忘了那一点,给你......

World::chunk* World::newChunk(int side, int height){
cout << "newChunk side: "<<std::to_string((long long)side) << endl;
cout << "newChunk height: "<<std::to_string((long long)height) << endl;
chunk* ch = new chunk();
ch->bm = newBlankBlockmap(side,height);
ch->fm = newBlankFloatmap(side);
return ch;

}

在哪里...

struct chunk {
    blockmap bm;
    floatmap fm;
};

定义在世界级

4

2 回答 2

2

重申评论暗示的内容:从您发布的内容来看,您的代码结构似乎很糟糕。像这样的三指针结构short***几乎不可能调试,应该不惜一切代价避免。您收到的堆损坏错误消息表明您在代码中的某处有错误的内存访问,这在您当前的设置中无法自动找到。

此时,您唯一的选择是手动挖掘整个代码,直到找到错误,或者开始重构。后者现在可能看起来更耗时,但如果您计划将来使用此代码,则不会。

考虑以下可能的重构提示:

  • 不要使用普通数组来存储值。std::vector同样有效并且更容易调试。
  • 避免简单newdelete. 在具有 STL 容器和智能指针的现代 C++ 中,纯内存分配只应在极少数例外情况下发生。
  • 始终对您的数组访问操作进行范围检查。如果您担心性能,请使用在发布版本中消失的断言,但请确保在需要进行调试时进行检查。
  • 在 C++ 中建模三维数组可能很棘手,因为operator[]只提供对一维数组的支持。一个不错的折衷方案是使用operator(),它可以采用任意数量的索引。
  • 避免 C 风格的强制转换。它们可能非常不可预测。使用 C++ casts static_castdynamic_castreinterpret_cast不是。如果您发现自己reinterpret_cast经常使用,那么您的设计中的某个地方可能存在错误。
于 2012-03-03T10:18:47.637 回答
0

这条线有问题short*** bm = new short**[sideLen];。内存是为sideLen元素分配的,但分配行bm[i][j][k] = blocks->getAIR_BLOCK();需要一个具有 size 的数组sideLen * sideLen * h。要解决此问题,需要将第一行更改short*** bm = new short**[sideLen * sideLen * h];为。

于 2012-03-03T10:14:53.897 回答