1. File *fp;
2. fp = fopen ("/etc/myfile.txt", "w");
3. fclose(fp);
现在
在语句1中,在堆栈上创建了类型为“FILE”的指针的4字节内存。
在语句2中,在堆上分配了memory ='sizeof(FILE)',并且其地址被分配给指针'fp'。
有人可以在声明2上解释更多。我们是否为所有文件分配相同的堆大小? O.S如何知道它应分配的文件大小?
在低级别,在第2阶段到底发生了什么。
答案 0 :(得分:4)
步骤1在堆栈上分配指针(如果它在函数中),或者如果在函数外部将引用全局空间中的现有保留位置(数据段或类似) - 在后一种情况下,这是在编译时保留的时间,即由编译器确定,而不是在运行时分配。指针在32位环境中为4个字节,在64位环境中为8个字节。
第2步调用fopen()
。该行本身不分配内存,但fopen()
的实现可能会这样做。你不知道它分配了什么,因为它依赖于实现。但是,您可以非常确定它将分配大小为sizeof FILE
的结构。您还知道fopen()
用于缓冲I / O,因此它可能会分配缓冲区,或者这可能是在您第一次使用该文件时完成的。您无法知道,因为它依赖于实现。但是,POSIX <stdio.h>
指定缓冲区的长度为BUFSIZ
,所以可以肯定的是,当它实际上被分配时,它至少会达到这个大小,因此当缓冲区被分配时,它将会在至少大小为BUFSIZ
的内存结构中。不要求它在堆上(它可以直接用mmap
调用MAP_ANON
并保留指向它的指针);再次,它依赖于实现。但是,公平的赌注是它在堆上。
第3步调用fclose()
。这将释放在步骤2中进行的分配,但不释放在步骤1中进行的分配(如果有的话)。
重新提问'操作系统如何知道FILE
'的大小:FILE
是一个C结构(实际上是typedef
的{{ 1}})。因此,它的大小对于C编译器是已知的,并且将被传递给所使用的任何分配器,例如,堆分配器。如果使用堆分配器,操作系统甚至都不会看到它,因为它将在您的C库中处理。
也许您会混淆磁盘上文件的大小struct
。 FILE
不是磁盘上的文件,它是C FILE
,它是该文件的缓冲I / O的控制结构,并且将包括(例如)文件描述符。该文件不会(通常)完全加载到RAM中。它的一小部分(缓冲区)被加载,POSIX标准表示缓冲区的长度应为typedef struct
。请参阅:http://pubs.opengroup.org/onlinepubs/009695399/basedefs/stdio.h.html
答案 1 :(得分:0)
步骤1中在堆栈上分配的指针不一定是4个字节,因为它取决于实现。
步骤2不仅为文件分配FILE
结构,还分配缓冲区(BUFSIZ字节),而不是整个文件的空间。所以它不需要知道文件有多大。