【问题标题】:Memory allocation when fopen is called is not clear调用 fopen 时的内存分配不清楚
【发布时间】:2014-02-01 14:13:43
【问题描述】:
1. File *fp;
2. fp = fopen ("/etc/myfile.txt", "w");
3. fclose(fp);

现在

I read this:

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

在语句 2 中,内存 = 'sizeof(FILE)' 在堆上分配,其地址分配给指针 'fp'。

有人可以对语句 2 进行更多解释。我们是否为所有文件分配相同的堆大小?操作系统如何知道它应该分配的 FILE 的大小?
在低级别,st 2 中究竟发生了什么。

【问题讨论】:

  • FILE * 结构与您认为的任何实际文件无关。它只是一个描述符结构,操作系统稍后会使用它来对文件执行 I/O。它的大小是恒定的,与它所描述的文件的大小完全无关。
  • @H2CO3:准确地说,操作系统不使用FILE;而是由 C 库使用(至少,对于类似 Linux 的操作系统是这样)。操作系统本身使用通过系统调用提供的文件描述符。
  • @OliCharlesworth 是的,太糟糕了,我现在无法编辑我的评论。当然它是由标准库使用的。

标签: c memory-management


【解决方案1】:

第 1 步在堆栈上分配一个指针(如果它在函数中),或者如果在函数外部,将引用全局空间(数据段或类似)中的现有保留位置 - 在后一种情况下,这是在编译时保留的时间,即由编译器确定,而不是在运行时分配。指针在 32 位环境下为 4 个字节,在 64 位环境下为 8 个字节。

第 2 步调用 fopen()。该行本身不分配内存,但fopen() 的实现可能会很好。您不知道这分配了什么,因为它取决于实现。但是,您可以确定它将分配大小为sizeof FILE 的结构。您还知道fopen() 用于缓冲I/O,因此它可能会分配一个缓冲区,或者这可能会在您第一次使用该文件时完成。您无法知道,因为它取决于实现。但是,POSIX <stdio.h> 指定缓冲区的长度为 BUFSIZ,因此可以肯定的是,当它实际上被分配时,它至少是那个大小,所以当缓冲区确实被分配时,它将在内存中结构至少大小为BUFSIZ。不要求它在堆上(它可以直接用MAP_ANON 调用mmap 并保留指向它的指针);同样,它依赖于实现。但是,公平的赌注是它在堆上。

第 3 步调用 fclose()。这将释放在第 2 步进行的分配,但不会释放在第 1 步进行的分配(如果有)。

你的问题'操作系统如何知道FILE 的大小'FILE 是一个 C 结构(实际上是一个 typedef 对应一个 struct)。因此,它的大小对于 C 编译器是已知的,并将传递给使用的任何分配器,例如堆分配器。如果使用堆分配器,这对操作系统来说甚至是不可见的,因为它将在您的 C 库中处理。

也许您将磁盘上文件的大小与FILE 的大小混淆了。 FILE 不是磁盘上的文件,它是一个 C typedef struct,它是该文件的缓冲 I/O 的控制结构,并且将包括(例如)文件描述符。该文件未(通常)完全加载到 RAM 中。它的一小部分(缓冲区)已加载,POSIX 标准规定缓冲区的长度应为BUFSIZ。见:http://pubs.opengroup.org/onlinepubs/009695399/basedefs/stdio.h.html

【讨论】:

    【解决方案2】:

    在步骤 1 中分配在堆栈上的指针不一定是 4 个字节,因为它取决于实现。

    第 2 步不仅为文件分配了一个FILE 结构,还为文件分配了一个缓冲区(BUFSIZ 字节),而不是为整个文件分配空间。所以它不需要知道文件有多大。

    【讨论】:

      猜你喜欢
      • 2011-11-14
      • 1970-01-01
      • 2011-05-09
      • 2013-09-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多