fflush(stdout)in c

时间:2010-10-29 21:25:07

标签: c stdout fflush

当我在fflush(stdout)并且我在GDB中打破时,在我实际打印它之前我能知道stdout中有什么吗?

我怎么能知道stdout在任何时间点有什么?

4 个答案:

答案 0 :(得分:2)

如果您自己分配缓冲区并将其传递给setvbuf,我认为您可以在刷新之前访问它,因为它是您的开始。

编辑:您的评论使您的意图更加明确,但您想要的并不容易:

  1. 如上所述设置自己的缓冲区
  2. stdout上设置read watchpoint
  3. 让您的程序慢慢爬行。
  4. 从那时起,gdb每次任何访问stdout时都会中断,您可以检查缓冲区是否有变化,奇怪的输出等等。

    那就是说,这根本不是一个理想的解决方案。一种更好的方法是在代码中的任何地方使用启用日志记录的输出函数。

答案 1 :(得分:1)

我认为最好刷新stdout,这意味着您基本上可以看到屏幕上或文件中的内容(如果stdout被重定向)。

答案 2 :(得分:1)

你几乎可以肯定,但你可能不应该。该标准仅要求FILE是一种对实现有用的类型,以识别打开的文件以及实现在流上运行的各种函数的语义所需的任何状态。

我通常同意其他海报fflush()是了解您实际写入文件的可靠方式。

但是,如果您忘记了代码的哪些部分可能正在写入流,那么有时候观察流中的流并捕捉它会发生变化。

实际上,FILEstruct的typedef,它由您的实现在头文件stdio.h中声明(通常命名为struct _iobuf)。虽然典型的实现只是轻微地记录其成员,但是典型的实现也实现了putchar()和它的一些朋友作为宏,这些宏也可以在stdio.h中找到。这与您可能与gdb一起使用的任何工具链的C运行时库的可能可用性相结合,可以为您提供所需的所有信息。

MinGW GCC 3.4.5中提供的stdio.h实现FILE如下:

typedef struct _iobuf
{
    char*   _ptr;
    int _cnt;
    char*   _base;
    int _flag;
    int _file;
    int _charbuf;
    int _bufsiz;
    char*   _tmpfname;
} FILE;

// oversimplify declaration of _iob[] here for clarity:
extern FILE _iob[FOPEN_MAX];    /* An array of FILE imported from DLL. */
//...
#define STDIN_FILENO    0
#define STDOUT_FILENO   1
#define STDERR_FILENO   2
#define stdin   (&_iob[STDIN_FILENO])
#define stdout  (&_iob[STDOUT_FILENO])
#define stderr  (&_iob[STDERR_FILENO])

并实现putchar()作为内联函数,利用GCC扩展到C:

__CRT_INLINE int __cdecl __MINGW_NOTHROW putchar(int __c)
{
  return (--stdout->_cnt >= 0)
    ?  (int) (unsigned char) (*stdout->_ptr++ = (char)__c)
    :  _flsbuf (__c, stdout);}

从这里可以看出成员_ptr指向缓冲区的末尾,并推断出char *中唯一的其他struct _iobuf_base)指向缓冲区的开头。成员_cnt显然是缓冲区中剩余的未使用字符数。函数_flsbuf()必须取第一个不适合的字符,并在将当前缓冲区内容写入文件并恢复_cnt字段后将其放在缓冲区的开头。

因此,如果您看到stdout->_baseBUFSIZ - stdout->_cnt,那么对于此实现,您将显示当前缓冲区中的数量和内容。

答案 3 :(得分:0)

使用“setbuf()”,并保留缓冲区的句柄,您可以查看。不幸的是,我不知道如何找到未刷新数据的偏移和长度。