读入我不应该访问的堆内存?

问题描述 投票:0回答:3

在下面的示例中,我分配了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? (为什么我可以访问它?;分配的内存不应该位于编译器找到的第一个空闲内存块中,并且不连接到数组的缓冲区吗?)

c heap-memory
3个回答
1
投票

为了避免不必要的数据移动,当分配为[[reduce]]时,realloc()重用同一内存块,并简单地减小其大小,将剩余部分返回堆。将内存返回堆,不会更改其内容或使其不可访问,并且C不会执行任何边界检查,因此,如果您编写代码访问不属于分配的内存,它将让您受益。

严格来说是

undefined behaviour

,所以可能会有其他行为,但是通常C不会生成代码来执行所需的最低要求以外的任何工作-在某些情况下可能会支持调试。

1
投票
“最可能的现实是,操作系统提供了一种方法来分配虚拟页面的区域(不一定是真实内存,应将其视为”假装/伪造内存”),并且malloc()可以分配“假装/伪造内存”(如果需要,并分配更多的虚拟页面区域,如果需要,并分配虚拟页面的区域)。

0
投票
int arr[5] = {0}; // these 5 integers are kept on the stack of the function int *ptr = &arr[0]; // the pointer ptr is also on the stack and points to the address of arr[0] ptr = malloc(5 * sizeof(int)); // malloc creates heap of size 5 * sizeof int and returns a ptr which points to it // the ptr now points to the heap and not to the arr[] any more. arr[9] = 15; //the array is of length 5 and arr[9] is out of the border of maximum arr[4] ! ptr = realloc(ptr, 1 * sizeof(int)); //this does only increase the heap to size 6 * sizeof int; for (int i = 0; i < 10; ++i) // undefined behavior! { printf("%d\n", arr[i]); } free(ptr); return 0;`

0
投票
这是您的代码上的一些重要事实,请参阅我的评论:
© www.soinside.com 2019 - 2024. All rights reserved.