17

The stdio is usually buffered. When I hit a breakpoint and there's a printf before the breakpoint, the printed string may still be in the buffer and I can not see it.

I know I can flush the stdio by adding some flush code in the program. Without doing this, is there any way to tell GDB to flush the stdio of the program being debugged after GDB stops? This way is more friendly when debugging a program.

Yorkwar
  • 1,204
  • 1
  • 11
  • 27

4 Answers4

15

Many recent UNIX stdio implementations will flush all buffers if you call fflush(NULL):

(gdb) call fflush(0)

If you don't have libc debug symbols installed, you may have to tell GDB about the type of fflush:

(gdb) call ((void(*)(int))fflush)(0)

But normally you shouldn't have to do that: if you called printf (and not fprintf), that goes stdout, which goes to your terminal, which would normally be line-buffered. So, so long as your printf printed a new line, the buffer would have been flushed after printf returned.

Employed Russian
  • 199,314
  • 34
  • 295
  • 362
  • 1
    The behaviour of `fflush( NULL )` is well-defined as flushing *all* output streams. Any implementation *not* doing this is not standard-compliant. – DevSolar Nov 15 '12 at 07:31
  • 1
    It works very well in my WinXP + MinGW + GDB, thanks. – ollydbg23 Jun 14 '14 at 05:39
  • Just make sure you don't do this from *inside* a stdio function that might be holding locks on some `FILE` objects, to avoid deadlock or corruption. (i.e. you can't safely do this at an arbitrary point in a program you interrupt while it's running.) – Peter Cordes Apr 05 '19 at 08:25
  • I get: 'fflush@plt' has unknown return type; cast the call to its declared return type – Rebroad Mar 18 '20 at 03:10
  • 1
    @Rebroad So do what it tells you to? Something like `call ((void(*)(int))fflush)(0)`. Or install libc6-dbg or similar, so GDB knows the type of `fflush`. – Employed Russian Mar 18 '20 at 03:45
3

GDB lets you call C functions directly from the command line. So you could do

(gdb) call setbuf(stdout, NULL)

Now, the only problem with that is that I don't know of a way to 'get' the real value of stdout at runtime.

EDIT This might help (from the docs):

call setbuf(fdopen(1, "w"), 0)
sehe
  • 374,641
  • 47
  • 450
  • 633
  • @Yorkwar: Found a possible 'hacky' way to get setbuf to work on the stdout fd via a duplicate stream object. Don't know about side-effects. Could you give it a whirl? – sehe Nov 24 '11 at 01:57
  • `(gdb) call setbuf(stdout, 0)` works. My probram is in C. But the solution is gdb tells the program, not gdb do it itself. And buffer for stdio is disabled all the time, which can affect the performance of the program. However, it's a workaround. – Yorkwar Nov 24 '11 at 03:45
1

If you define a function in your program:

void flush_all(void) {
    fflush(NULL);
}

you can call this function from within gdb(1) with:

call flush_all()

A short demo:

$ cat cat.c
#include <stdio.h>

int main(int argc, char* argv[]) {
    printf("this is a partial write");
    printf("this is a partial write");
    printf("this is a partial write");
    printf("this is a partial write");
    printf("this is a partial write");

    return 0;
}

void flush_all(void) {
    fflush(NULL);
}

$ gcc -g -o cat cat.c
$ gdb
GNU gdb (Ubuntu/Linaro 7.2-1ubuntu11) 7.2
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
(gdb) file cat
Reading symbols from /home/sarnold/tmp/cat...done.
(gdb) break printf
Breakpoint 1 at 0x400428
(gdb) run
Starting program: /home/sarnold/tmp/cat 

Breakpoint 1, __printf (format=0x4006bc "this is a partial write") at printf.c:30
30  printf.c: No such file or directory.
    in printf.c
(gdb) cont
Continuing.

Breakpoint 1, __printf (format=0x4006bc "this is a partial write") at printf.c:30
30  in printf.c
(gdb) cont
Continuing.

Breakpoint 1, __printf (format=0x4006bc "this is a partial write") at printf.c:30
30  in printf.c
(gdb) call flush_all()
this is a partial writethis is a partial write(gdb) ^CQuit
(gdb) quit
sarnold
  • 102,305
  • 22
  • 181
  • 238
  • 1
    I think of a workaround with "commands" of GDB: `(gdb) commands 1-N >call flush_all() >end` Where N is large number to cover all my breakpoints – Yorkwar Nov 24 '11 at 03:48
0

You can use the display command as in (gdb) display, the details of which can be found here. Once GDB hits an end-of-line character like "\n", the output will be displayed. You can turn off the display using undisplay.

MLev
  • 421
  • 1
  • 6
  • 16