2010-10-29 3 views
2

Справа, когда я нахожусь в fflush (stdout), и я там ломаюсь в GDB, могу ли я узнать, что есть в stdout, прежде чем я его распечатаю?fflush (stdout) in c

Как я могу узнать, что есть в стандартном режиме в любой момент времени?

+0

Я думаю, что я не объяснил это хорошо. В основном, когда моя программа заканчивается и сбрасывает stdout, я вижу странный o/p. Вот почему я хочу постоянно контролировать stdout, чтобы увидеть, что пишет, когда и кем. – hari

+0

Что произойдет, если вы переключитесь на небуферизованный вывод с помощью 'setvbuf (stdout, NULL, _IONBF, 0)'? –

ответ

1

Вы почти наверняка можете, но вы, вероятно, не должны. Стандарт требует только того, чтобы FILE был типом, который полезен для реализации, для идентификации открытого файла и любого состояния, необходимого для реализации семантики различных функций, работающих с потоками.

Я бы согласился с другими плакатами, что fflush() - это надежный способ узнать, что вы на самом деле писали в файл.

Однако, если вы потеряли информацию о том, какие части вашего кода могут писать в поток, тогда это может быть полезно для просмотра потока в действии и его изменения.

На практике FILE является ЬурейиМ для struct, заявленная вашей реализация в заголовочном файле stdio.h (часто с именем struct _iobuf). Хотя типичная реализация только слегка документирует своих членов, типичная реализация также реализует putchar() и некоторые из ее друзей как макросы, которые также находятся в stdio.h. Это, в сочетании с вероятной доступностью источников для библиотеки времени выполнения C любой инструментальной цепочки, которую вы, вероятно, будете использовать с gdb, доставит вам всю информацию, необходимую для просмотра под капотом.

Stdio.h предоставлено в MinGW GCC 3.4.5 реализует 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, для этой реализации вы бы указали, сколько и что находится в текущем буфере.

1

Я думаю, что лучше сбросить stdout, что означает, что в основном вы видите содержимое на экране или в файле (если перенаправлено stdout).

0

используйте «setbuf()» и держите дескриптор в буфере, который вы можете заглянуть. К сожалению, я не знаю, как найти смещение и длину несплошных данных.

2

Если вы сами выделили буфер и передали его setvbuf, я полагаю, вы можете получить к нему доступ до флеша, так как это ваше начало.

EDIT: Ваш комментарий сделал ваше намерение более ясно, но то, что вы хотите, не будет легко:

  1. Настройте свой собственный буфер, как описано выше,
  2. Установите read watchpoint на stdout,
  3. Следите за своей программой с медленным скачком.

С тех пор, gdb сломается каждый раз ничего обращающийся stdout, и вы можете проверить буфер изменения, странный вывод и т.д.

, что сказал, что это не является идеальным решением вообще. В гораздо лучшем подходе будет использоваться функция вывода с включенным протоколированием в вашем коде.

+0

Один улов: нет гарантии, что 'setvbuf' даже будет использовать буфер, который вы ему даете. Он может выбрать только использовать его, если он больше, чем существующий внутренний буфер, или всегда игнорировать его ... –

Смежные вопросы