Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to tell GDB to flush the stdio of the program being debugged

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.

like image 923
Yorkwar Avatar asked Nov 24 '11 01:11

Yorkwar


People also ask

How do you get out of continue in gdb?

You should interrupt the process that is attached by gdb. Do not interrupt gdb itself. Interrupt the process by either ctrl-c in the terminal in which the process was started or send the process the SIGINT by kill -2 procid.

At which point does gdb stop a running program?

gdb will stop your program at whatever line it has just executed. From here you can examine variables and move through your program. To specify other places where gdb should stop, see the section on breakpoints below.


3 Answers

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.

like image 177
Employed Russian Avatar answered Sep 19 '22 13:09

Employed Russian


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)
like image 33
sehe Avatar answered Sep 19 '22 13:09

sehe


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
like image 1
sarnold Avatar answered Sep 19 '22 13:09

sarnold