【问题标题】:What happens when we dereference a FILE pointer?当我们取消引用 FILE 指针时会发生什么?
【发布时间】:2015-09-10 12:45:22
【问题描述】:

假设我有一个文件指针

FILE* infile = fopen("<somefilepath", "r");

现在当我取消引用 gdb 中的文件指针时,我得到了

打印 *infile

│$2 = {_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' }

谁能帮我理解这意味着什么?

【问题讨论】:

  • 这就是 FILE 在您的库实现中包含的内容。如果您想知道所有这些成员的意思,那么答案将太长,对于本网站来说既过于宽泛又过于具体..
  • 对任何其他结构都意味着相同。

标签: c pointers


【解决方案1】:

FILE * 应该被视为一个不透明的值...取消引用它将取决于平台/库(因此不可移植)。

【讨论】:

    【解决方案2】:

    C11 7.21.1/2 将FILE 描述为

    …一种能够记录所有需要的信息的对象类型 控制一个流,包括它的文件位置指示器,一个指向 其关联的缓冲区(如果有),记录的错误指示器 是否发生读/写错误,以及文件结束指示符 记录是否已到达文件末尾;

    但没有提到具体的成员。这是您观察到的 glibc 的实现(为了清楚起见,我删除了未使用的预处理器分支):

    struct _IO_FILE {
      int _flags;       /* High-order word is _IO_MAGIC; rest is flags. */
    #define _IO_file_flags _flags
    
      /* The following pointers correspond to the C++ streambuf protocol. */
      /* Note:  Tk uses the _IO_read_ptr and _IO_read_end fields directly. */
      char* _IO_read_ptr;   /* Current read pointer */
      char* _IO_read_end;   /* End of get area. */
      char* _IO_read_base;  /* Start of putback+get area. */
      char* _IO_write_base; /* Start of put area. */
      char* _IO_write_ptr;  /* Current put pointer. */
      char* _IO_write_end;  /* End of put area. */
      char* _IO_buf_base;   /* Start of reserve area. */
      char* _IO_buf_end;    /* End of reserve area. */
      /* The following fields are used to support backing up and undo. */
      char *_IO_save_base; /* Pointer to start of non-current get area. */
      char *_IO_backup_base;  /* Pointer to first valid character of backup area */
      char *_IO_save_end; /* Pointer to end of non-current get area. */
    
      struct _IO_marker *_markers;
    
      struct _IO_FILE *_chain;
    
      int _fileno;
      int _flags2;
      _IO_off_t _old_offset; /* This used to be _offset but it's too small.  */
    
    #define __HAVE_COLUMN /* temporary */
      /* 1+column number of pbase(); 0 is unknown. */
      unsigned short _cur_column;
      signed char _vtable_offset;
      char _shortbuf[1];
    
      /*  char* _save_gptr;  char* _save_egptr; */
    
      _IO_lock_t *_lock;
    
      _IO_off64_t _offset;
      void *__pad1;
      void *__pad2;
      void *__pad3;
      void *__pad4;
      size_t __pad5;
      int _mode;
      /* Make sure we don't get into trouble again.  */
      char _unused2[15 * sizeof (int) - 4 * sizeof (void *) - sizeof (size_t)];
    };
    

    【讨论】:

      【解决方案3】:

      FILE 在 C 标准第 7.21.1 节中有所描述:

      2 声明的类型是 size_t(在 7.19 中描述);

          文件

      这是一种能够记录所有信息的对象类型 需要控制一个流,包括它的文件位置指示器,一个 指向其关联缓冲区(如果有)的指针,错误指示器 记录是否发生读/写错误,以及文件结束 记录是否已到达文件末尾的指示器; ...

      在您的特定情况下,您似乎正在使用 glibc。 FILE 的实现可以在 libio.h 中找到:

      struct _IO_FILE {
        int _flags;       /* High-order word is _IO_MAGIC; rest is flags. */
      #define _IO_file_flags _flags
      
        /* The following pointers correspond to the C++ streambuf protocol. */
        /* Note:  Tk uses the _IO_read_ptr and _IO_read_end fields directly. */
        char* _IO_read_ptr;   /* Current read pointer */
        char* _IO_read_end;   /* End of get area. */
        char* _IO_read_base;  /* Start of putback+get area. */
        char* _IO_write_base; /* Start of put area. */
        char* _IO_write_ptr;  /* Current put pointer. */
        char* _IO_write_end;  /* End of put area. */
        char* _IO_buf_base;   /* Start of reserve area. */
        char* _IO_buf_end;    /* End of reserve area. */
        /* The following fields are used to support backing up and undo. */
        char *_IO_save_base; /* Pointer to start of non-current get area. */
        char *_IO_backup_base;  /* Pointer to first valid character of backup area */
        char *_IO_save_end; /* Pointer to end of non-current get area. */
      
        struct _IO_marker *_markers;
      
        struct _IO_FILE *_chain;
      
        int _fileno;
      #if 0
        int _blksize;
      #else
        int _flags2;
      #endif
        _IO_off_t _old_offset; /* This used to be _offset but it's too small.  */
      
      #define __HAVE_COLUMN /* temporary */
        /* 1+column number of pbase(); 0 is unknown. */
        unsigned short _cur_column;
        signed char _vtable_offset;
        char _shortbuf[1];
      
        /*  char* _save_gptr;  char* _save_egptr; */
      
        _IO_lock_t *_lock;
      #ifdef _IO_USE_OLD_IO_FILE
      };
      

      请记住,完整的实现跨越许多文件、函数、数据结构等。

      【讨论】:

        猜你喜欢
        • 2015-02-24
        • 2012-09-20
        • 1970-01-01
        • 2011-08-08
        • 2016-08-21
        • 1970-01-01
        • 2013-04-29
        • 2023-03-29
        • 1970-01-01
        相关资源
        最近更新 更多