【问题标题】:How to redirect std::cin to a Linux terminal when debugging with GDB?使用 GDB 调试时如何将 std::cin 重定向到 Linux 终端?
【发布时间】:2014-08-10 15:50:15
【问题描述】:

在 Linux 中,GDB 不允许使用 set new-console on,而是使用名为 tty 的东西。与

set inferior-tty /dev/pts/[number of an active console],

在 .gdbinit 文件中(每次都需要编辑数字)它重定向 std::cout,但 std::cin 无法正常工作。它只是将我的输入解释为好像我正在发送 bash 命令并报告错误,并且我的程序继续等待输入。在那之后我不能再在控制台中输入,所以我假设std::cin 正在被重定向,但不能正常工作。

我尝试查找如何从应用程序本身启动终端。我只能找到this answer,其中还提到了一个错误,它不会重定向输入。

有没有办法解决这个问题,并在调试时将std::cin(和std::cout)正确重定向到 Linux 终端?


背景信息:我想做的事情应该很简单。在使用 std::cin 之前,在用户输入前打印 >。我有简单的代码打印>,刷新cout,然后调用getline()。它在正常运行程序时起作用。但遗憾的是,当没有换行符时,GDB 拒绝刷新流,因此它不打印 >,忽略用户输入的第一个字符,然后 确实 打印 @987654336 @,紧随其后的是我的程序由于输入字符串残缺而发送的错误消息。

在 Windows 中,我通过使用 set new-console on 创建一个 .gdbinit 文件解决了这个问题。这会导致 GDB 使用 Windows 控制台而不是它自己的控制台,并且按预期工作。

【问题讨论】:

    标签: c++ linux terminal gdb cin


    【解决方案1】:

    如果您需要在程序有机会暂停后开始调试,只需在终端中运行程序,然后在另一个终端中运行gdb - your-program-pid。否则,有一系列步骤比描述要快。

    1. 启动两个终端窗口。
    2. 在一个终端中,找出 shell 的 PID。 ps 应该会告诉你。
    3. 在另一个终端中,使用这些命令

      $ gdb - pid-of-the-other-shell
      (gdb) br main
      (gdb) c
      
    4. 现在您已将 gdb 附加到另一个终端中的 shell。不是很有用。

    5. 在第一个终端中,在 shell 提示符下键入

      $ exec your-program
      

    现在您有一个终端运行gdb,另一个终端在gdb 下运行您的程序,停在main。请记住,当程序退出时,其终端窗口将关闭。如果您不希望这样,请在第一个终端中启动第二级 shell 并将 gdb 附加到它。

    您也可以使用set inferior-tty 命令,但您必须确保其他 tty 存在并且没有其他程序尝试从中读取。最简单的方法是在另一个终端中运行一个 shell 并给它一个while true; do sleep 1000; done 命令。请注意,您可能会收到 warning: GDB: Failed to set controlling terminal: Operation not permitted 消息。它们是无害的。

    【讨论】:

    • while true; do sleep 1000; done 的东西有效!它似乎不是所有解决方案中最优雅的,但它是迄今为止唯一对我有用的解决方案。我执行了你的五个步骤(顺便说一下,我不得不在步骤 3 的第一行使用 sudo),但是在输入 exec 命令后,什么也没有发生,终端不再接受输入。
    • 在 exec 命令之后,程序在 main停止。您必须在 gdb 中使用“step”或“continue”命令。
    • 啊,你是对的。键入 continue 使其开始正常。不过,我想我仍然会坚持使用睡眠循环。因为它允许我从 Eclipse 启动调试。
    【解决方案2】:

    您可以使用 gdb 的多进程调试功能和像 xterm 这样的终端模拟器来执行此操作。 (gnome-terminal 不会像后面解释的那样好用)

    prompt.c

    #include <stdio.h>
    
    int main()
    {
        enum {
            N = 100,
        };
        char name[N];
    
        printf("> ");
        scanf("%s", name);
        printf("Hi, %s\n", name);
        return 0;
    }
    

    xterm.gdb

    关闭分叉分离 设置目标异步 关闭分页 设置不间断 文件 /usr/bin/xterm # -ut 告诉 xterm 不要写 utmp 日志记录 # 涉及root权限 设置参数 -ut -e ./prompt 赶上执行 跑步

    示例会话

    $ gdb -q -x xterm.gdb
    Catchpoint 1 (exec)
    <...>
    [New process 7073]
    <...>
    Thread 0x7ffff7fb2780 (LWP 7073) is executing new program: /home/scottt/Dropbox/stackoverflow/gdb-stdin-new-terminal/prompt
    Reading symbols from /home/scottt/Dropbox/stackoverflow/gdb-stdin-new-terminal/prompt...done.
    
    Catchpoint 1 (exec'd /home/scottt/Dropbox/stackoverflow/gdb-stdin-new-terminal/prompt), 0x0000003d832011f0 in _start () from /lib64/ld-linux-x86-64.so.2
    (gdb) inferior 2
    [Switching to inferior 2 [process 7073] (/home/scottt/Dropbox/stackoverflow/gdb-stdin-new-terminal/prompt)]
    [Switching to thread 2 (Thread 0x7ffff7fb2780 (LWP 7073))] 
    #0  0x0000003d832011f0 in _start () from /lib64/ld-linux-x86-64.so.2
    (gdb) break prompt.c:11
    Breakpoint 2 at 0x4004b4: file prompt.c, line 11.
    (gdb) continue &
    Continuing.
    (gdb) 
    Breakpoint 2, main () at prompt.c:11
    11      printf("> ");
    next
    12      scanf("%s", name);
    (gdb) next
    13      printf("Hi, %s\n", name);
    

    执行gdb -q -x xterm.gdb 后会出现一个新的xterm 窗口,您可以在其中与prompt 进行交互,而不会干扰GDB。

    相关的 GDB 命令:

    我使用xterm 是因为gnome-terminal 使用dbus-launch 要求另一个进程在GDB 所依赖的父子进程关系之外启动新终端。

    【讨论】:

    • 当我调试它时,它似乎启动了 xterm 终端片刻,但随后我立即收到一条错误消息,说它在应用程序运行时无法更改目标异步设置:i.imgur.com/xuBqqaX.png .我不确定是 GDB、Xterm 还是 Eclipse 导致了这种情况。我试过摆弄调试配置设置并注释掉 xterm.gdb 的一些行,但我无法让它工作。谷歌搜索错误显示了一群有完全相同的错误但没有解决方案的人。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-07-11
    • 2015-04-28
    • 1970-01-01
    • 1970-01-01
    • 2019-08-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多