-4

此代码导致与 Visual Studio 2010 对应的堆损坏。是什么导致堆损坏?这段代码的哪一部分导致了它?

#define size 65536
int main()
{
    int* a =  new int[size];//size is equal to
    srand(time(NULL));
    for(int i = 0 ; i < size; i++)
    {
        a[i]= 1 + rand() % 10;
    }

    for(int i = 0;  (size / 2) / pow((double)2, i)>= 1; i++)
    {
        int n = pow((double)2, i);
        int offset = 0;
        for(int j = 0; j < (size / 2) / pow((double)2, i); j++)
        {
            int* tmp = new int[n];
            merge(a + offset, n, a + offset + n, n, tmp);
            memcpy(a + offset, tmp, n*2 * sizeof(int));
            offset += pow((double)2, i+1);
        }
    }

    for(int i = 0; i < size; i++)
    {
        cout<<a[i]<<" ";
    }
    cout<<endl;
    system("PAUSE");
    return 0;
}
4

3 回答 3

3

怀疑 memcpy 是问题所在。您正在从 tmp 复制 (n * 2 * sizeof(int)) 字节,而您只为其分配了 n * sizeof(int) 。

于 2012-04-29T16:36:33.690 回答
1

堆损坏仅仅意味着您分配了一块内存,然后在该块之外写入数据。通常这意味着您已经写过了数组的末尾。

少量覆盖将命中放置在您的内存分配之后的“警戒词”,因此运行时将在您的程序继续正常运行时检测并报告堆损坏。但是,如果您进一步编写,您可能会损坏其他一些关键数据(当您的程序尝试使用数据时导致未定义的结果)或运行超出内存映射的末尾并给出致命的访问冲突错误。

检查数组中的索引是否始终在 0..Length-1 范围内

如果您无法计算所使用的最大索引是多少,则输入一行代码以检查索引是否在此范围内,如果不在则进入调试器。即检查您传递给merge/memcpy 的值是否始终在范围内。(可能是他们写了一个元素太多 - 一个快速的问题是分配比你“需要”更多的内存,但这显然不是正确的解决方案 - 你需要确保你只写你想要的数据至)

于 2012-04-29T16:37:40.903 回答
1

您没有为以下内容分配足够的空间tmp

int* tmp = new int[2*n];

合并代码中的递增for (..; ...; c_i++)看起来也很可疑。

您可能有几个错误,使用调试器或编写跟踪消息并检查发生了什么 - 确认您没有写出越界。

于 2012-04-29T16:38:05.693 回答