我是初学者,我不明白为什么这段代码不会崩溃。当我使用 malloc(1) 分配平面时,怎么会有这么多平面[i]?
int main()
{
typedef struct Flight2{
int altitude;
int longitude;
int latitude;
}Flight;
Flight *planes;
planes = (Flight*)malloc(1);
if (planes == NULL) {
printf("Error in allocating the data array.n");
}
printf("%d.n",sizeof(Flight));
planes[0].altitude = 1000;
planes[100].altitude = 1200;
printf("0: %dn",planes[0].altitude);
free((void*)planes);
printf("100: %d",planes[100].altitude);
return 0;
}
首先,您在访问planes
数组的第一个位置具有未定义的行为。从那一刻起,任何事情都可能发生。但是,以下是对您的案例中实际发生的事情的解释。我在这里所说的永远不应该被依赖,然而,了解幕后发生的事情是有益的。
您的结构大小为 12 字节(至少在我的系统上)。因此,100 个Flight
对象需要 1200 字节的内存。这很重要,因为系统根据内存页来管理进程的内存,而内存页在 X86 硬件上有 4096 字节。所以,发生的事情是这样的:
-
您从
malloc()
请求一个字节。 -
malloc()
实现还没有内存输出,所以它要求系统内核提供内存。 -
系统内核至少为
malloc()
实现提供一整页。 -
malloc()
实现将一些私有数据写入内存页,以便能够将其分成许多小块返回给您。 -
malloc()
实现返回该页中的指针。这很可能指向比它存储自己的私人数据更高的地址。但这取决于malloc()
实现。 -
从此指针写入偏移量 0 到 3 和 1188-1191 的内存。
这不会失败,因为它仍在内存页中,因此硬件和系统内核认为此访问是可以的。(仅)
malloc()
的定义与您正在做的事情相冲突。 -
由于您没有破坏
malloc()
实现的任何重要私人数据,因此free()
调用没有意识到发生了可疑的事情,并且您的程序正常终止。
请注意,程序的明显成功行为取决于其中只有一个分配的事实。如果在第一个调用之后插入第二个malloc()
调用,则可能会崩溃,因为可能会覆盖malloc()
实现专用的数据。这可能会导致free()
中止程序并显示错误消息,导致其他malloc()
调用的错误行为,以任何方式使程序崩溃或执行任何其他操作。如果在第一个调用前面插入第二个malloc()
调用,则可能会导致分配发生在内存页的末尾,这可能会给您带来段错误。但是,一旦你进入不确定行为的土地,没有什么是确定的。
顺便说一句:如果你用valgrind
运行你的程序,它会准确地告诉你哪里出了问题以及如何出错。这确实是一个很棒的工具,您应该熟悉它。