我可以用gdb转储stdin吗?

时间:2015-06-26 13:26:49

标签: c debugging gdb stdin

我正在调试一个用C编写的简单应用程序,并在用户输入的代码段中发现了一个错误:

char ch = getchar();  // get user choice
getchar();            // discard ENT

switch(ch) {          // switch user choice
    case -1:
        return 0;
        break;
    case 'n':
        // do something
        break;
    default:
}

这有点缩写,但重点是我使用getchar()从用户那里获取单个字符输入,然后根据该输入做出一些决定。

如果用户在getchar()提示时输入一个字符串,这会导致程序中的破坏,因为我的输入缓冲区有多个字符,并且(因为我在上面的结构上循环)每个后续的循环迭代将在剩余的字符上执行直到缓冲区为空。不用说,这是不受欢迎的行为。我想要一个来自用户的角色。我认为应该很简单,使用fgets()或在getchar()周围添加一些逻辑,以确保它丢弃不需要的字符,只需使用第一个。

我的问题,使用上面的应用程序作为一个简单的例子,是:

我在gdb中调试此应用程序时是否可以转储stdin的内容?

例如,假设我没有弄清楚这个bug的来源,并试图找出为什么当我进入“hello world!”时,我的应用程序会吐出一堆“垃圾”。在用户提示符而不是'h'。如果我在switch语句之前中断,是否可以命令gdb转储stdin以便我可以看到输入缓冲区中剩下什么(如果有的话)?

以下是我在gdb中的位置示例:

Reading symbols from /cygdrive/c/Users/OwenS.BCI/Desktop/ex19.exe...done.
(gdb) break ex19.c:147
Breakpoint 1 at 0x4015b8: file ex19.c, line 147.
(gdb) run
Starting program: /cygdrive/c/Users/OwenS.BCI/Desktop/ex19.exe
[New Thread 784.0x1d98]
[New Thread 784.0xdc0]
You enter the The great hall.

> hello world!

Breakpoint 1, process_input (game=0x8003b390) at ex19.c:148
148             switch(ch) {
(gdb) print ch
$1 = 104 'h'
(gdb) print stdin
No symbol "stdin" in current context.
(gdb) ???

顺便说一下,这个应用实例取自“学习C艰难之路”的练习19。

1 个答案:

答案 0 :(得分:2)

  

我在gdb

中调试此应用程序时是否可以转储stdin的内容

是的,但要这样做,您需要知道正在使用的libc的内部,并且您需要libc将调试信息编译到其中。

在Linux上,您将安装libc6-debuginfo或类似的包,然后打印_IO_stdin符号,该符号将包含指向包含缓冲数据的内部缓冲区的指针。

但你使用的是cygwin libc,而且我对它的内部结构并不熟悉。

<强>更新

  

我相信我理解如何编译cygwin DLL以允许在其版本的libc中进行调试,但是有关如何找出相关调试符号的任何建议?

通过预处理器运行以下源的最简单方法:

#include <stdio.h>
int main() { FILE *f = stdin; }

并查看预处理源的最后一行。如果stdin #define_IO_stdin类似{{1}},则可以清楚地看到。