0

可能重复:
在 malloc() 之后写入指针越界不会导致错误

我正在尝试一个非常基本的程序来为只有 2 的数组分配内存ints。我只为 2 分配内存ints,即array[0], 和array[1]: 为什么可以使用array[2]并且运行良好?

#include <stdio.h>

int main(int argc, char *argv[])
{
    int *array;
    int i;
    array = NULL;
    array = malloc(sizeof(int)*2);

    array[0] = 2;
    array[1] = 3;
    array[2] = 4;

    for( i = 0; i<3 ; i++)
    printf("%d\n", array[i]);

    return 0;
}

输出:

 2
 3
 4
4

6 回答 6

3

在此处阅读答案以获得更好的理解

本质上是内存损坏,如此处所述

尝试使用一个非常大的数字而不是 4,它会产生错误,因为当您调用 malloc() 时,一小块内存会从一个较大的页面中为您雕刻出来。所以写超出你的块的范围并不一定意味着你会崩溃。在数组 [4] 中,您不会在为该初始块分配的页面范围之外写入内容,因此您在技术上是在写入有效的映射地址。资源

于 2012-08-16T17:33:53.757 回答
3

似乎可行,因为 C 不会阻止您访问不属于您的内存。即使它看起来可以工作,代码仍然不正确,明天可能无法工作。您通过写入/读取不属于您的内存来调用未定义的行为。

于 2012-08-16T17:24:48.160 回答
2

pb2q 是绝对正确的。一种可能验证您正在访问未分配内存的方法是执行以下操作:

array = calloc(sizeof(int) * 2); 
for (i = 0; i < 3; i++)
    printf("%d\n", array[i]);

您可能会收到以下输出:

0
0
*random value*
于 2012-08-16T17:34:43.527 回答
0

我相信它有效,因为您的实现malloc 在内存块之前和之后放置了一些信息,并且可能以块的形式分配(例如,将分配请求四舍五入到最接近的 64 个字节)。malloced 内存必须能够被释放,这需要一些关于其大小等的信息,这些信息放在分配的内存之前和/或之后。

如果数据是按块分配的,那么您可以达到一些限制,您可以完全填满一个“块”,并且读取array[n]将在“块”的末尾进行。我们可以这样测试:

int main() {
    int i;
    char * a;
    for (i = 1; i < 10000; i++) {
        a = malloc(i);
        a[i] = 'x';
        printf("%d %c\n", i, a[i]);
        free(a);
    }
    return 0;
}

malloc是越来越大的内存块,并检查越界的段错误。我得到的截断输出是:

1 x
[...]
58 x
59 x
60 x
61 x
62 x
*** glibc detected *** ./a.out: free(): invalid next size (normal): 0x0a041008 ***
[...]

即尝试a = malloc(63); a[63] = 'x';失败,因为它破坏了我之前谈论的元数据。

于 2012-08-16T17:37:46.653 回答
0

因为C不会试图握住你的手。您可以读取/写入未分配的内存,但您很可能会修改/从其他对象中提取数据,或者只是提取垃圾数据。

当你创建一个数组时,你会得到一个指向内存地址的指针,你可以随意使用它。通过分配内存,您可以防止在该内存块中创建其他对象,就像您为数组保留它一样。但是,超过该数量没有限制,您可以在任何您喜欢的地方读写。这样做的好处是你有相当大的权力,可以直接操纵地址。不利的一面是,您可以很容易地使您的程序在属于其他对象的内存位置上的操作信息崩溃。

从中得到的一点是,C 给了你很大的权力,而这种权力的使用完全取决于你。

于 2012-08-16T17:32:41.470 回答
0

这是提示:您必须避免在函数上使用 printf ...仅在 main() 内使用它(:

当你使用 malloc 和 realloc 时,C 将分配一个 int 大小的内存。它不会分配另一个“位置”来放置数字。唯一发生的情况是,如果您放入的数据具有与 int 相同的字节大小。这通常会发生,因为 C 不会告诉您数组大小是否已满。小心点。

于 2012-08-16T18:15:44.960 回答