Domanda
Proprio quando sono a fflush (stdout) e io ci spezzo in GDB, posso sapere cosa c'è in stdout prima che io in realtà stamparlo?
Come faccio a sapere cosa c'è in stdout in qualsiasi punto nel tempo?
Soluzione
È quasi certamente possibile, ma probabilmente non dovrebbe. La norma richiede soltanto che FILE
essere un tipo che è utile per la realizzazione di identificare un file aperto e qualunque stato è necessario per attuare la semantica delle varie funzioni che operano sui flussi.
Mi piacerebbe generalmente d'accordo con altri manifesti che fflush()
è un modo affidabile per sapere ciò che effettivamente scritto al file.
Tuttavia, se avete perso le tracce di ciò che parti del codice potrebbe aver scritto in un flusso, allora può a volte essere utile per vedere il flusso in azione e lo prende cambiando.
In pratica, FILE
è un typedef per una struct
che viene dichiarato da l'implementazione nel file di intestazione stdio.h (spesso chiamato struct _iobuf
). Anche se una tipica implementazione documenta solo leggermente i suoi membri, una tipica implementazione anche attrezzi putchar()
e alcuni dei suoi amici come macro che si trovano anche in stdio.h. Questo, combinato con la probabile disponibilità di fonti per la libreria di runtime C di qualsiasi toolchain si rischia di utilizzare con gdb, si ottiene tutte le informazioni necessarie per peek sotto il cofano.
Lo stdio.h fornite in MinGW GCC 3.4.5 implementa FILE
come segue:
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])
e attrezzi putchar()
come funzione inline approfittando di estensione GCC a C:
__CRT_INLINE int __cdecl __MINGW_NOTHROW putchar(int __c)
{
return (--stdout->_cnt >= 0)
? (int) (unsigned char) (*stdout->_ptr++ = (char)__c)
: _flsbuf (__c, stdout);}
Da questo si può dire che il fine del buffer è punta il _ptr
membro, e dedurre che l'unica altra char *
a struct _iobuf
(_base
) sta puntando l'inizio del buffer. Il _cnt
membro è chiaramente il conteggio dei caratteri non utilizzati rimanenti nel buffer. La _flsbuf()
funzione deve prendere il primo carattere che non si adatta e metterlo all'inizio del buffer dopo che ha scritto il contenuto del buffer corrente sul file e ripristinato il campo _cnt
.
Quindi, se si guarda stdout->_base
e BUFSIZ - stdout->_cnt
si sarebbe, per questa implementazione, avere un display di quanto e cosa è nel buffer corrente.
Altri suggerimenti
Se si alloca un buffer da soli e passarlo a setvbuf , I supporti possono accedervi prima di un colore, dal momento che è tuo per cominciare.
Modifica Il tuo commento fatto il vostro intento più chiaro, ma ciò che si vuole non sarà facile:
- Imposta il tuo tampone come descritto sopra,
- Imposta un leggere watchpoint su
stdout
, - Guarda il tuo programma di lenti a passo d'uomo.
Da allora in poi, gdb
romperà ogni volta niente accessi stdout
, e si può controllare il buffer per le modifiche, uscita strano, ecc.
Detto questo, che non è una soluzione ideale a tutti. Un approccio di gran lunga migliore sarebbe utilizzando una funzione di uscita di registrazione abilitata ovunque nel codice.
Credo che sia meglio stdout
a filo, che in pratica significa che state vedendo il contenuto sullo schermo o in un file (se stdout
viene reindirizzato).
l'uso "setbuf ()", e mantenere una maniglia per il buffer, che è possibile sbirciare. Purtroppo, non so fuori dalla parte superiore come trovare l'offset e la lunghezza dei dati unflushed.