为什么这会修复堆损坏?

Why does this fix a heap corruption?

所以我有代码:

    float **array = new float*[width + 1]; //old line was '= new float*[width]'

    //Create dynamic 2D array
    for (int i = 0; i < width; ++i) {
        array[i] = new float[height + 1]; //old line was '= new float[height]'
    }

    //Hardcode 2D array for testing
    for (int i = 0; i < height; ++i) {
        for (int j = 0; j < width; ++j) {
            array[i][j] = i + j;
         }
     }

    //deallocate heap memory
    for (int i = 0; i < width; ++i) {
        delete [] array[i]; //Where corrupted memory error used to be
    }
    delete [] array;

(郑重声明,我知道分配单个内存块会更有效,但我与永远不会理解 why/how 使用它的科学家密切合作。由于它在服务器上运行,老板们说这是首选。)

我的问题是为什么 height+1/width+1 可以修复损坏的内存问题?我知道额外的 space 用于空终止符,但为什么有必要?以及为什么当高度和宽度相同时它可以工作,但当它们不同时会中断?

索尔恩: 填充数组时我的 height/width 倒退了...... -.-;感谢 NPE。

以下评论是转移注意力的评论:

   delete [] array[i]; //Where corrupted memory error used to be

这不是内存错误发生的地方。这是 它被检测到的地方(由 C++ 运行时)。请注意,运行时没有义务检测 this sort of errors,因此在某种程度上它是在帮您一个忙。 :-)

您的代码部分有一个 buffer overrun(可能是循环中的差一错误),但您没有显示。

如果通过检查代码找不到它,请在 GCC 中尝试 Valgrind-fsanitize=address

编辑:您添加到问题中的代码存在问题:

//Hardcode 2D array for testing
for (int i = 0; i < height; ++i) {
    for (int j = 0; j < width; ++j) {
        array[i][j] = i + j;
     }
 }

是它有 widthheight(或者,等价地,ij)的错误方式。除非 width == height,您的代码有 undefined behaviour.

通过 height+1 和 weight+1 改变身高和体重可能是不够的。 您发布的代码在身高和体重方面是正确的。

这意味着在代码的其他部分中,有些东西可能刚好写在这些数组的末尾,当你增加这些数组时,它会使错误的代码直接写在数组的末尾而不是崩溃.你没有解决问题,你只是隐藏它。

由于 OS 检测堆损坏的方式存在一些限制,代码实际上在删除 [] 时崩溃了。堆上的差一错误通常会在下一次调用 new/delete/malloc/free 时检测到,而不是在它们实际发生时检测到。

如果您想确切知道您的程序何时何地使用指针进行非法操作,您可以使用 Valgrind 等工具。

您没有修复代码。您正在做的是用新代码更改可执行文件,从而将损坏错误转移到程序的另一部分。

有一件事你应该做——不要把你的程序改成你说的"works" + 1然后接受它。 我知道如果错误很难诊断,这可能很诱人,但不要走这条路。

你必须做的是回到非工作版本,真正解决问题。通过 "fix",意思是您可以解释修复的作用、修复问题的原因等。