简体   繁体   English

使用GDB进行调试时,如何将std :: cin重定向到Linux终端?

[英]How to redirect std::cin to a Linux terminal when debugging with GDB?

In Linux, GDB doesn't allow set new-console on and in stead uses something called tty . 在Linux中,GDB不允许在其中set new-console on而是使用名为tty的东西。 With

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

in a .gdbinit file (requires editing the number every time) it redirects std::cout , but std::cin isn't working properly. 在.gdbinit文件中(每次都需要编辑数字),它重定向std::cout ,但std::cin无法正常工作。 It just interprets my input as if I'm sending a bash command and reports an error, and my program continues to wait for input. 它只是将我的输入解释为好像我正在发送bash命令并报告错误,并且我的程序继续等待输入。 I can no longer type in the console after that, so I assume std::cin is being redirected, but doesn't work properly. 之后,我将无法再在控制台中键入内容,因此我认为std::cin 被重定向,但无法正常工作。

I tried looking up how to launch a terminal from the application itself. 我尝试查找如何从应用程序本身启动终端。 I could only find this answer , which also mentions a bug that it doesn't redirect input. 我只能找到这个答案 ,其中还提到了一个不重定向输入的错误。

Is there any way to fix this issue and redirect std::cin (and std::cout ) to a Linux terminal properly when debugging? 有什么方法可以解决此问题,并在调试时将std::cin (和std::cout )正确重定向到Linux终端?


Background info: What I'm trying to do should be simple. 背景信息:我想要做的应该很简单。 Print a > in front of user input before using std::cin. 使用std :: cin之前,请在用户输入前打印> I have simple code in place that prints the > , flushes cout and then calls getline() . 我有简单的代码来打印> ,刷新cout然后调用getline() It works when just running the program normally. 当正常运行程序时,它可以工作。 But sadly, GDB refuses to flush the stream when there isn't a newline, so it doesn't print the > , ignores the first character of the user input and then does prints the > , immediately followed by the error message that my program sends because of the mutilated input string. 但可悲的是,GDB拒绝刷新流时,没有一个换行符,所以它不打印> ,忽略用户输入的第一个字符,然后打印> ,紧接着是错误消息我的计划由于输入字符串残缺而发送。

In Windows, I've solved it by making a .gdbinit file with set new-console on . 在Windows中,我通过在.gdbinit文件上set new-console on来解决此问题。 This causes GDB to use a Windows console in stead of its own and that works as intended. 这导致GDB代替自己的Windows控制台使用Windows控制台,并且按预期方式工作。

If you need to start the debugging after the program has a chance to pause, just run the program in a terminal, and then gdb - your-program-pid in another terminal. 如果您需要在程序有机会暂停后开始调试,只需在终端中运行该程序,然后在另一个终端中运行gdb - your-program-pid Otherwise there's a sequence of steps which is faster to do than to describe. 否则,有一系列步骤比描述要快。

  1. Start two terminal windows. 启动两个终端窗口。
  2. In one terminal, figure out the PID of the shell. 在一个终端中,找出外壳的PID。 ps should tell you. ps应该告诉你。
  3. In the other terminal, use these commands 在另一个终端中,使用以下命令

     $ gdb - pid-of-the-other-shell (gdb) br main (gdb) c 
  4. Now you have gdb attached to your shell in another terminal. 现在,您已将gdb附加到另一个终端上的shell中。 Not very useful. 不太有用。

  5. In the first terminal, type at the shell prompt 在第一个终端中,在shell提示符下键入

     $ exec your-program 

Now you have one terminal running gdb and another terminal running your program under gdb , stopped at main . 现在,您有一个运行gdb终端,另一个在gdb下运行程序的终端,该终端在main停止。 Bear in mind that when the program exits, its terminal window will close. 请记住,程序退出时,其终端窗口将关闭。 If you don't want this, start a second level shell in the first terminal and attach gdb to it. 如果您不希望这样做,请在第一个终端中启动第二层Shell,然后将gdb附加到它。

You can also use set inferior-tty command, but you must make sure the other tty exists and no other program attempts to read from it. 您也可以使用set inferior-tty命令,但是必须确保另一个tty存在并且没有其他程序尝试从中读取。 The easiest way is to run a shell in another terminal and give it a while true; do sleep 1000; done 最简单的方法是在另一个终端中运行一个shell并给它一段while true; do sleep 1000; done while true; do sleep 1000; done while true; do sleep 1000; done command. while true; do sleep 1000; done命令。 Note that you may get warning: GDB: Failed to set controlling terminal: Operation not permitted messages. 请注意,您可能会收到warning: GDB: Failed to set controlling terminal: Operation not permitted消息。 They are harmless. 他们是无害的。

You can use gdb's multiprocess debugging feature and a terminal emulator like xterm to do this. 您可以使用gdb的多进程调试功能和类似xterm的终端仿真器来执行此操作。 ( gnome-terminal won't work so well as explained later) gnome-terminal不能像后面解释的那样很好地工作)

prompt.c 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 xterm.gdb

set detach-on-fork off
set target-async on
set pagination off
set non-stop on

file /usr/bin/xterm
# -ut tells xterm not to write a utmp log record
# which involves root privileges
set args -ut -e ./prompt
catch exec

run

Sample Session 样品会议

$ 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);

A new xterm window will appear after executing gdb -q -x xterm.gdb and you can interact with prompt inside it without interfering with GDB. 在执行gdb -q -x xterm.gdb后,将出现一个新的xterm窗口,您可以与其中的prompt进行交互而不会干扰GDB。

Related GDB commands: 相关的GDB命令:

I used xterm because gnome-terminal uses dbus-launch to ask another process to launch the new terminal outside of the parent-child process relationship that GDB relies on. 我使用xterm是因为gnome-terminal使用dbus-launch来要求另一个进程在GDB依赖的父子进程关系之外启动新的终端。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM