Search code examples
cgnuc99glibclibc

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


I am reading the source of glibc-2.19. I found that if I use fopen to get a pointer of FILE, the buffer of the stdio has been already existing. When and where did it allocated and initialized ?


Solution

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

    It's unclear exactly what you found, or how. Normally the buffer that FILE uses is not allocated until you try to read or write something to the FILE.

    Example:

    #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
    $1 = {
      _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 '\000',
      _shortbuf = "",
      _lock = 0x6020f0,
      _offset = -1,
      __pad1 = 0x0,
      __pad2 = 0x602100,
      __pad3 = 0x0,
      __pad4 = 0x0,
      __pad5 = 0,
      _mode = 0,
      _unused2 = '\000' <repeats 19 times>
    }
    

    Above you can clearly see that none of the internal buffers: _IO_read_ptr, _IO_read_end, etc. have been allocated yet.

    Now let's set a watchpoint on &fp->_IO_read_ptr and next:

    (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
    

    Now you can see that attempt to read from the FILE does cause the buffer to be allocated in _IO_new_file_underflow.