我是初学者,我不明白为什么这段代码不会崩溃。当我使用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: %d\n",planes[0].altitude);
free((void*)planes);
printf("100: %d",planes[100].altitude);
return 0;
}
答案 0 :(得分:3)
首先,您在访问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
运行程序,它会告诉您出错的确切位置以及方式。这是一个非常好的工具,你应该熟悉它。