为什么stdout无法替代?

时间:2014-01-30 09:05:13

标签: c stdout glibc

出于教育目的,我正在尝试替换标准流stdout,stdin和stderr。我首先查找了流的数据类型,我追溯到带有以下成员的struct _IO_FILE(gdb ptype _IO_FILE):

type = struct _IO_FILE {
    int _flags;
    char *_IO_read_ptr;
    char *_IO_read_end;
    char *_IO_read_base;
    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;
    short unsigned int _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[20];
}

然后我试图复制stdout指针的内存内容:

_IO_FILE f1 = {._flags = -72540028, ._offset = -1, ._old_offset = -1, ._fileno = 1, ._chain = stdin, ._lock = stdout->_lock, .__pad2 = stdout->__pad2 };
_IO_FILE *f2 = stdout;
_IO_FILE *f3 = malloc(sizeof(_IO_FILE));
memcpy(f3, stdout, sizeof(_IO_FILE));

fprintf(&f1, "f1\n"); // doesn't work 
fprintf(f2, "f2\n"); // works
fprintf(f3, "f3\n"); // doesn't work

但是,只有指针赋值不会崩溃。我通过gdb比较了内存​​内容,并且所有内容共享相同的结构成员内容。

虽然这个问题可能与平台有关:fprintf和其他库函数只是将指针与标准流进行比较吗?

编辑:我怀疑,这是一个实施或平台相关的问题,因为所有意见都表明,我接受了答案,这表明了问题的一个可能原因。

edit2:缩小问题的范围:我使用的是64位ubuntu版本12.04和EGLIBC版本2.15。

1 个答案:

答案 0 :(得分:1)

根据来自Corvus的评论,在Linus系统上,锁与流相关联,因此复制FILE数据结构会干扰锁语义。

(我建议不要立即接受这个答案,让Corvus有时间回答。)


旧假设:

我怀疑,在你的C实现中,FILE对象的位置被用作其含义的一部分。例如,可能存在它们的数组,并且从指向FILE对象的指针中减去指向数组的第一元素的指针以在数组中找到其索引。然后,此索引将用作系统调用中的文件编号,例如write

分配新空间时,它不在此数组中,指针算术会产生错误的结果。