3

就在我在 fflush(stdout) 并在 GDB 中中断时,我可以在实际打印之前知道 stdout 中有什么吗?

我怎样才能知道任何时候标准输出中有什么?

4

4 回答 4

2

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

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

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

从那时起,gdb每次访问都会中断,您可以检查缓冲区是否有更改、奇怪的输出等stdout

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

于 2010-10-29T21:30:30.693 回答
1

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

于 2010-10-29T21:28:19.047 回答
1

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

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

但是,如果您忘记了代码的哪些部分可能正在写入流,那么观察流的运行情况并捕捉它的变化有时会很有用。

实际上,FILE是 a 的 typedef,struct由您的实现在头文件 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->_base并且BUFSIZ - stdout->_cnt对于此实现,您会显示当前缓冲区中有多少和什么。

于 2010-10-29T21:56:12.097 回答
0

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

于 2010-10-29T21:29:09.360 回答