当我在使用GDB进行debug时,在fflush(stdout)处断点,是否可以在实际打印之前知道stdout中的内容?
如何在任意时间点了解stdout中的内容?
setvbuf
不保证一定会使用你提供的缓冲区。它可能仅在该缓冲区大于现有内部缓冲区时才使用它,或者完全忽略它... - R.. GitHub STOP HELPING ICEFILE
是一种对于实现有用的类型,用于识别打开的文件和实现操作流的各种函数所需的任何状态。fflush()
是了解实际写入文件内容的可靠方法。FILE
是一个由你的实现在头文件stdio.h中声明的struct
的typedef(通常命名为struct _iobuf
)。虽然典型的实现只轻微地记录其成员,但典型的实现也将putchar()
及其某些友元实现为宏,这些宏也可以在stdio.h中找到。结合你使用gdb的任何工具链的C运行时库的源代码的可能可用性,这就为你提供了查看底层的所有信息。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])
并且利用C语言的GCC扩展,将putchar()
实现为内联函数:
__CRT_INLINE int __cdecl __MINGW_NOTHROW putchar(int __c)
{
return (--stdout->_cnt >= 0)
? (int) (unsigned char) (*stdout->_ptr++ = (char)__c)
: _flsbuf (__c, stdout);}
从这里可以看出,缓冲区的末尾由成员_ptr
指向,并且可以推断出struct _iobuf
中唯一的另一个char *
(_base
)指向缓冲区的开头。成员_cnt
显然是剩余未使用字符的计数。函数_flsbuf()
必须将无法容纳的第一个字符放在缓冲区的开头,在将当前缓冲区内容写入文件并恢复_cnt
字段之后。
因此,如果您观察stdout->_base
和BUFSIZ - stdout->_cnt
,则对于此实现,您将显示当前缓冲区中有多少内容以及是什么内容。
我认为最好刷新stdout
,这基本意味着您可以在屏幕上或文件中(如果stdout
被重定向)看到内容。
setvbuf(stdout, NULL, _IONBF, 0)
切换到无缓冲输出会发生什么? - Adam Rosenfield