glibc:何时何地分配和初始化 stdio 流缓冲区?

glibc: When and where is the stdio stream buffer allocated and initialized?

我正在阅读 glibc-2.19 的源代码。我发现如果我用fopen得到一个FILE的指针,stdio的buffer已经存在了。何时何地分配和初始化?

I found that if I use fopen to get a pointer of FILE, the buffer of the stdio has been already existing.

不清楚您到底找到了什么,或者如何找到的。通常 FILE 使用的缓冲区是 未分配 直到您尝试读取或写入某些内容到 FILE.

示例:

#include <stdio.h>

int main()
{
  FILE *fp = fopen("/etc/passwd", "r");
  int c = fgetc(fp);
  return 0;
}

gcc -g t.c && gdb -q ./a.out
Reading symbols from ./a.out...done.
(gdb) start
Temporary breakpoint 1 at 0x400535: file t.c, line 5.
Starting program: /tmp/a.out

Temporary breakpoint 1, main () at t.c:5
5     FILE *fp = fopen("/etc/passwd", "r");
(gdb) n
6     int c = fgetc(fp);
(gdb) p *fp
 = {
  _flags = -72539000,
  _IO_read_ptr = 0x0,
  _IO_read_end = 0x0,
  _IO_read_base = 0x0,
  _IO_write_base = 0x0,
  _IO_write_ptr = 0x0,
  _IO_write_end = 0x0,
  _IO_buf_base = 0x0,
  _IO_buf_end = 0x0,
  _IO_save_base = 0x0,
  _IO_backup_base = 0x0,
  _IO_save_end = 0x0,
  _markers = 0x0,
  _chain = 0x7ffff7dd41c0 <_IO_2_1_stderr_>,
  _fileno = 3,
  _flags2 = 0,
  _old_offset = 0,
  _cur_column = 0,
  _vtable_offset = 0 '[=10=]0',
  _shortbuf = "",
  _lock = 0x6020f0,
  _offset = -1,
  __pad1 = 0x0,
  __pad2 = 0x602100,
  __pad3 = 0x0,
  __pad4 = 0x0,
  __pad5 = 0,
  _mode = 0,
  _unused2 = '[=10=]0' <repeats 19 times>
}

在上面你可以清楚地看到 none 个内部缓冲区:_IO_read_ptr_IO_read_end 等已经分配了。

现在让我们在 &fp->_IO_read_ptrnext 上设置一个观察点:

(gdb) watch -l fp._IO_read_ptr
Hardware watchpoint 3: -location fp._IO_read_ptr
(gdb) next
Hardware watchpoint 3: -location fp._IO_read_ptr

Old value = 0x0
New value = 0x7ffff7ff7000 ""
0x00007ffff7a8f689 in _IO_new_file_underflow (fp=0x602010) at fileops.c:608
608 fileops.c: No such file or directory.
(gdb) bt
#0  0x00007ffff7a8f689 in _IO_new_file_underflow (fp=0x602010) at fileops.c:608
#1  0x00007ffff7a9062e in __GI__IO_default_uflow (fp=0x602010) at genops.c:435
#2  0x00007ffff7a86bae in _IO_getc (fp=0x602010) at getc.c:39
#3  0x00000000004005a4 in main () at t.c:6

现在您可以看到尝试从 FILE 中读取确实会导致在 _IO_new_file_underflow 中分配缓冲区。