Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
(struct\u IO\u FILE*)是如何实现的->_IO_读取_基本设置?_C_File_Unix_Glibc_Stdio - Fatal编程技术网

(struct\u IO\u FILE*)是如何实现的->_IO_读取_基本设置?

(struct\u IO\u FILE*)是如何实现的->_IO_读取_基本设置?,c,file,unix,glibc,stdio,C,File,Unix,Glibc,Stdio,为这个可能很奇怪的问题标题道歉。我不想让它看起来像一个标题为“C文件I/O如何在低级别工作?”的傻瓜。我希望我的问题是明确的 无论如何,当文件在C中是fopen'd时,它返回一个struct\u IO\u文件* FILE *f = fopen("hello.txt", "r"); printf("Fileno: %i\n", f->_fileno); // 3 我已经查看了libio.h和gdb的“tab”输出,并确认struct\u IO\u文件的内容如下所示: struct _IO_

为这个可能很奇怪的问题标题道歉。我不想让它看起来像一个标题为“C文件I/O如何在低级别工作?”的傻瓜。我希望我的问题是明确的

无论如何,当文件在C中是
fopen
'd时,它返回一个
struct\u IO\u文件*

FILE *f = fopen("hello.txt", "r");
printf("Fileno: %i\n", f->_fileno); // 3
我已经查看了
libio.h
和gdb的“tab”输出,并确认
struct\u IO\u文件的内容如下所示:

struct _IO_FILE {
  int _flags;
  char* _IO_read_ptr;
  char* _IO_read_end;
  char* _IO_read_base; // <-- file contents
  char* _IO_write_base;
  char* _IO_write_ptr;
  char* _IO_write_end;
  char* _IO_buf_base;
  char* _IO_buf_end;
  char *_IO_save_base;
  char *_IO_backup_base;
  char *_IO_save_end;
  struct _IO_marker *_markers;
  struct _IO_FILE *_chain;
  int _fileno;
  int _flags2;
  __off_t _old_offset;
  unsigned short _cur_column;
  signed char _vtable_offset;
  char _shortbuf[1];
  _IO_lock_t *_lock;
  __off64_t _offset;
  void *__pad1;
  void *__pad2;
  void *__pad3;
  void *__pad4;
  size_t __pad5;
  int _mode;
  char _unused2[...];
};
您可以看到它在哪里变换。在genops的某个地方。大概是
\uuuuflow()
。但其来源没有回答任何问题:

int
__uflow (fp)
     _IO_FILE *fp;
{
#if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
  if (_IO_vtable_offset (fp) == 0 && _IO_fwide (fp, -1) != -1)
    return EOF;
#endif

  if (fp->_mode == 0)
    _IO_fwide (fp, -1);
  if (_IO_in_put_mode (fp))
    if (_IO_switch_to_get_mode (fp) == EOF)
      return EOF;
  if (fp->_IO_read_ptr < fp->_IO_read_end)
    return *(unsigned char *) fp->_IO_read_ptr++;
  if (_IO_in_backup (fp))
    {
      _IO_switch_to_main_get_area (fp);
      if (fp->_IO_read_ptr < fp->_IO_read_end)
    return *(unsigned char *) fp->_IO_read_ptr++;
    }
  if (_IO_have_markers (fp))
    {
      if (save_for_backup (fp, fp->_IO_read_end))
    return EOF;
    }
  else if (_IO_have_backup (fp))
    _IO_free_backup_area (fp);
  return _IO_UFLOW (fp);
}
libc_hidden_def (__uflow)
int
__uflow(fp)
_IO_文件*fp;
{
#如果定义| LIBC |定义| GLIBCPP |使用| WCHAR |
如果(_IO_vtable_offset(fp)=0&&u IO_fwide(fp,-1)!=-1)
返回EOF;
#恩迪夫
如果(fp->_模式==0)
_IO_fwide(fp,-1);
如果(输入模式(fp))
如果(_IO_切换到_get_模式(fp)=EOF)
返回EOF;
如果(fp->IO读取ptrIO读取结束)
返回*(无符号字符*)fp->_IO_read_ptr++;
如果(_IO_in_backup(fp))
{
_IO_开关_至_主_获取_区域(fp);
如果(fp->IO读取ptrIO读取结束)
返回*(无符号字符*)fp->_IO_read_ptr++;
}
如果(_IO_有_标记(fp))
{
如果(为备份保存(fp,fp->IO读取结束))
返回EOF;
}
否则如果(有备份(fp))
_IO空闲备份区(fp);
返回流(fp);
}
libc_hidden_def(uu uflow)
在gdb中测试每个调用,每个if检查都失败,所以我只能假设它返回
\u IO\u UFLOW(fp)。有趣的是,_IO_UFLOW是
\u UFLOW
的一个宏包装器,所以…它在调用自己。它不是无限递归的。为什么?


这样一来,我就陷入了死胡同,因为我仍然无法解释
fp->IO\u read\u ptr
是如何填写的。我只知道它发生在
genops.c

的某个地方,在GDB中支持硬件观察点的平台上,您可以通过在
fp->\u IO\u read\u base
上设置观察点来简单地回答这个问题。例如:

(gdb) watch -l fp->_IO_read_base
Hardware watchpoint 2: -location fp->_IO_read_base
(gdb) c
Continuing.
Hardware watchpoint 2: -location fp->_IO_read_base

Old value = 0x0
New value = 0x7ffff7ff7000 ""
__GI__IO_switch_to_get_mode (fp=fp@entry=0x602010) at genops.c:191
191 genops.c: No such file or directory.
(gdb) bt
#0  __GI__IO_switch_to_get_mode (fp=fp@entry=0x602010) at genops.c:191
#1  0x00007ffff7a8f670 in _IO_new_file_underflow (fp=0x602010) at fileops.c:602
#2  0x00007ffff7a841a5 in _IO_getdelim (lineptr=0x7fffffffdc88, n=0x7fffffffdc90, delimiter=10, fp=0x602010) at iogetdelim.c:77
#3  0x00000000004005b7 in main () at t.c:9

几乎可以肯定的是,libc_hidden_def(u uflow)
是一种棘手的弱引用类型,它允许您使用同名的其他函数重写函数。@paxdiablo您知道,有时我会质疑GNU开发人员的理智。当然,他们是一流的软件,但当你看源代码时,会发现宏意大利面、过多的空白、奇怪的缩进,以及各种可怕的、噩梦般难以阅读的代码,这些代码看起来就像是直接来自地狱的代码高尔夫挑战。有人想知道,他们是如何保持这种状态的。再说一次,也许他们已经。。。
(gdb) watch -l fp->_IO_read_base
Hardware watchpoint 2: -location fp->_IO_read_base
(gdb) c
Continuing.
Hardware watchpoint 2: -location fp->_IO_read_base

Old value = 0x0
New value = 0x7ffff7ff7000 ""
__GI__IO_switch_to_get_mode (fp=fp@entry=0x602010) at genops.c:191
191 genops.c: No such file or directory.
(gdb) bt
#0  __GI__IO_switch_to_get_mode (fp=fp@entry=0x602010) at genops.c:191
#1  0x00007ffff7a8f670 in _IO_new_file_underflow (fp=0x602010) at fileops.c:602
#2  0x00007ffff7a841a5 in _IO_getdelim (lineptr=0x7fffffffdc88, n=0x7fffffffdc90, delimiter=10, fp=0x602010) at iogetdelim.c:77
#3  0x00000000004005b7 in main () at t.c:9