首页 > 解决方案 > 读入我不应该访问的堆内存?

问题描述

在下面的示例中,我分配了 20 字节的内存来将数组扩展 5 个整数。之后,我将最后一个元素设置为 15,然后将指针重新分配为 4 个字节(1 个整数)。然后我打印数组的前 10 个元素(此时它只包含 6 个),第 9 个(我之前设置为 15)打印时没有警告或错误。

编码 :

#include <stdlib.h>
#include <stdio.h>

int main()
{
    int arr[5] = {0};
    int *ptr = &arr[0];
    ptr = malloc(5 * sizeof(int));
    arr[9] = 15;
    ptr = realloc(ptr, 1 * sizeof(int));
    for (int i = 0; i < 10; ++i)
    {
        printf("%d\n", arr[i]);
    }
    free(ptr);
    return 0;
}

编译运行后的结果:

0
0
0
0
0
32766
681279744
-1123562100
-1261131712
15

我的问题如下:为什么数组的第 9 个元素还是 15?(为什么我可以访问它?;分配的内存不应该在我的编译器找到的第一个空闲内存块上,并且不连接到数组的缓冲区吗?)

标签: cheap-memory

解决方案


您对程序正在做什么的描述都是错误的。

在下面的示例中,我分配了 20 个字节的内存来将数组扩展 5 个整数

不,你没有。你不能延长arr。这是不可能的。

之后我将最后一个元素设置为 15

否 - 因为您没有扩展数组,所以索引 9 不代表最后一个元素。您只需在数组外部写入。

看看这些行:

int *ptr = &arr[0];
ptr = malloc(5 * sizeof(int));

首先你ptr指出第一个元素,arr但在你ptr指出一些与arr. 换句话说 - 可以简单地删除第一行(编译器可能会删除)。

在您的程序的其余部分中,您永远不会使用ptr任何东西。换句话说 -您可以简单地使用删除所有代码ptr。它没有效果。

所以程序可以简单地是:

int main()
{
    int arr[5] = {0};
    arr[9] = 15;
    for (int i = 0; i < 10; ++i)
    {
        printf("%d\n", arr[i]);
    }
    return 0;
}

它具有未定义arr的行为,因为您访问越界。


推荐阅读