C ++文件输出函数中的神秘内存泄漏

时间:2016-11-19 17:15:17

标签: c++ memory-leaks gdb

我讨厌做旧的"这里有一些代码,它有什么问题?"但我几天来一直在调查这个问题而没有任何进展。这段代码通常会在调试器关闭的情况下立即崩溃,但偶尔会有几个小时的空间来编译并正确运行。附加gdb它可以工作,但每秒大约10 MB的内存泄漏,并在它耗尽时崩溃。

这绝对是这个功能;当对它的唯一调用被注释掉时,不会出现这样的问题,并且不经常调用它会延迟内存不足的崩溃。

 //Write a frame of the animation to disk
void draw_frame(int framenum) {
    ofstream fout;
    ostringstream fname;
    fname << "D:\\frames\\" << framenum << ".data";
    fout.open(fname.str(), ios::binary | ios::out);

    unsigned char ***frame;
    frame = new unsigned char ** [WORLDSIZE];
    for (int x = 0; x < WORLDSIZE; x++) {
        frame[x] = new unsigned char * [WORLDSIZE];
        for (int y=0; y < WORLDSIZE; y++) {
            frame[x][y] = new unsigned char [3];
        }
    }

    unsigned long long ***colormix;
    colormix = new unsigned long long ** [WORLDSIZE];
    for (int x = 0; x < WORLDSIZE; x++) {
        colormix[x] = new unsigned long long * [WORLDSIZE];
        for (int y=0; y < WORLDSIZE; y++) {
            colormix[x][y] = new unsigned long long [3];
            for (int z=0; z < 3; z++) {
                colormix[x][y][z]=0;
            }
        }
    }

    for (vector<SmellyObject *>::iterator it = smellythings.begin(); it != smellythings.end(); ++it) {
        SmellyObject *theobj = *it;
        for (int x=0; x < WORLDSIZE; x++) {
            for (int y=0; y < WORLDSIZE; y++) {
                double scentlevel = scentmaps[theobj -> id][x][y];
                double colorlevel = (scentlevel / 10000.0);
                colormix[x][y][0] += theobj->r * colorlevel;
                colormix[x][y][1] += theobj->g * colorlevel;
                colormix[x][y][2] += theobj->b * colorlevel;
            }
        }
    }

    for (int x=0; x < WORLDSIZE; x++) {
        for (int y=0; y < WORLDSIZE; y++) {
            for (int z=0; z < 3; z++) {
                //cout << colormix[x][y][z] << " ";
                frame[x][y][z] = min(255.0, (colormix[x][y][z] / (double) smellythings.size()));
            }
        }
    }

    for (int x=0; x < WORLDSIZE; x++) {
        for (int y=0; y < WORLDSIZE; y++) {
            fout.write((char *) frame[x][y], 3);
        }
    }

    fout.close();

    frame = new unsigned char ** [WORLDSIZE];
    for (int x = 0; x < WORLDSIZE; x++) {
        frame[x] = new unsigned char * [WORLDSIZE];
        for (int y=0; y < WORLDSIZE; y++) {
            for (int z=0; z < WORLDSIZE; z++) {
                //delete[] &frame[x][y][z];
            }
            delete[] frame[x][y];
        }
        delete[] frame[x];
    }
    delete[] frame;

    colormix = new unsigned long long ** [WORLDSIZE];
    for (int x = 0; x < WORLDSIZE; x++) {
        colormix[x] = new unsigned long long * [WORLDSIZE];
        for (int y=0; y < WORLDSIZE; y++) {
            for (int z=0; z < WORLDSIZE; z++) {
                //delete[] &colormix[x][y][z];
            }
            delete[](colormix[x][y]);
        }
        delete[](colormix[x]);
    }
    delete[](colormix);

    return;
}

WORLDSIZE是50,scentmapsstd::unordered_map映射整数(SmellyObject的.id属性)到WORLDSIZE x WORLDSIZE双精度数组。

1 个答案:

答案 0 :(得分:1)

frame = new unsigned char ** [WORLDSIZE];

您在函数的开头分配此数组,然后继续分配其所有三个维度,吞噬大量内存。

然后,稍后......

fout.close();

frame = new unsigned char ** [WORLDSIZE];

...您刚刚将frame重新分配给另一个已分配的数组。旧frame指针消失了,您刚刚泄露了最初分配的公吨内存。

与您的其他colormix数组相同的错误。

从中学到的教训:修复错误的最好方法是永远不要把它们放在首位。如果您使用的C ++容器正确处理了所有内存分配,例如std::vector,那么这种情况就不会发生。正确地使用C ++库的全部资源 - 容器,迭代器,算法 - 使逻辑上不可能发生许多常见的编程错误。