调用fopen时的内存分配不明确

时间:2014-02-01 14:13:44

标签: c memory-management

1. File *fp;
2. fp = fopen ("/etc/myfile.txt", "w");
3. fclose(fp);

现在

I read this

在语句1中,在堆栈上创建了类型为“FILE”的指针的4字节内存。

在语句2中,在堆上分配了memory ='sizeof(FILE)',并且其地址被分配给指针'fp'。

有人可以在声明2上解释更多。我们是否为所有文件分配相同的堆大小? O.S如何知道它应分配的文件大小?
在低级别,在第2阶段到底发生了什么。

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库中处理。

也许您会混淆磁盘上文件的大小structFILE不是磁盘上的文件,它是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字节),而不是整个文件的空间。所以它不需要知道文件有多大。