fflush(stdout)in c

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

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

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

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

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

实际上, FILE是一个struct的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()实现为内联函数,利用对C的GCC扩展:

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

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

所以,如果你观察stdout->_baseBUFSIZ - stdout->_cnt你可以在这个实现中显示当前缓冲区的数量和内容。

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

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

  1. 如上所述设置自己的缓冲区,
  2. stdout上设置读取观察点 ,
  3. 观看您的程序慢慢爬行。

从那时起, gdb将在每次访问stdout时中断,并且您可以检查缓冲区是否有变化,奇怪的输出等。

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

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

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