如何传递参数并将stdin从文件重定向到程序在gdb中运行?

时间:2010-12-23 17:20:32

标签: c++ debugging gdb

我通常运行一个程序:

./a.out arg1 arg2 <file

我想使用gdb调试它。

我知道set args功能,但只能从gdb提示符开始。

5 个答案:

答案 0 :(得分:408)

你可以这样做:

gdb --args path/to/executable -every -arg you can=think < of

神奇的位是--args

只需在gdb命令控制台中键入run即可开始调试。

答案 1 :(得分:134)

将参数传递给gdb中的run命令。

$ gdb ./a.out
(gdb) r < t
Starting program: /dir/a.out < t

答案 2 :(得分:4)

如果您想在run中使用gdb命令来执行带有重定向和参数的程序,可以使用set args

% gdb ./a.out
(gdb) set args arg1 arg2 <file
(gdb) run

我无法使用--args参数实现相同的行为,gdb严重地逃脱了重定向,即

% gdb --args echo 1 2 "<file"
(gdb) show args
Argument list to give program being debugged when it is started is "1 2 \<file".
(gdb) run
...
1 2 <file
...

这个实际上重定向了gdb本身的输入,而不是我们真正想要的

% gdb --args echo 1 2 <file
zsh: no such file or directory: file

答案 3 :(得分:1)

在您的项目上启动GDB。

  1. 转到项目目录,您已经编译了项目可执行文件。发出命令gdb和可执行文件的名称,如下所示:

    gdb projectExecutablename

  2. 启动gdb,打印以下内容: GNU gdb(Ubuntu 7.11.1-0ubuntu1~16.04)7.11.1 版权所有(C)2016 Free Software Foundation,Inc。 ................................................. 输入“apropos word”来搜索与“word”相关的命令...... 从projectExecutablename中读取符号...完成。 (GDB)

    1. 在开始运行程序之前,您需要设置断点。 break命令允许您这样做。在名为main的函数的开头设置断点:

      (gdb)b main

    2. 一旦你有了(gdb)提示符,run命令就会启动可执行文件的运行。如果要调试的程序需要任何命令行参数,请将它们指定给run命令。如果您想在“xfiles”文件(位于项目目录中的“mulder”文件夹中)上运行我的程序,您将执行以下操作:

      (gdb)r mulder / xfiles

    3. 希望这会有所帮助。

      免责声明:此解决方案不是我的,它改编自https://web.stanford.edu/class/cs107/guide_gdb.html 这个简短的gdb指南很可能是在斯坦福大学开发的。

答案 4 :(得分:0)

仅在任何命令前键入debug就能在外壳层使用gdb进行调试,这会很好吗?

此功能下方。它甚至可以与以下内容一起使用:

"$program" "$@" < <(in) 1> >(out) 2> >(two) 3> >(three)

这是一个您无法控制任何内容的调用,所有内容都是可变的,可以包含空格,换行符和shell元字符。在此示例中,inouttwothree是其他任意命令,它们消耗或产生不被破坏的数据。

在这种环境[Gist]中,跟随bash函数几乎可以干净地调用gdb

debug()
{
  1000<&0 1001>&1 1002>&2 \
  0</dev/tty 1>/dev/tty 2>&0 \
  /usr/bin/gdb -q -nx -nw \
  -ex 'set exec-wrapper /bin/bash -c "exec 0<&1000 1>&1001 2>&1002 \"\$@\"" exec' \
  -ex r \
  --args "$@";
}

如何应用此示例:只需在前面输入debug

之前:

p=($'\n' $'I\'am\'evil' "  yay  ")
"b u g" "${p[@]}" < <(in) 1> >(out) 2> >(two) 3> >(three)

之后:

p=($'\n' $'I\'am\'evil' "  yay  ")
debug "b u g" "${p[@]}" < <(in) 1> >(out) 2> >(two) 3> >(three)

就是这样。现在,使用gdb进行调试绝对是轻而易举。除了一些细节或更多:

  • gdb不会自动退出,因此将保持IO重定向打开,直到您退出gdb。但是我称它为功能。

  • 您无法像使用argv0一样容易地将exec -a arg0 command args传递给程序。请按照以下步骤操作:exec-wrapper之后,将"exec更改为"exec -a \"\${DEBUG_ARG0:-\$1}\"

  • 有FD处于打开状态的1000以上,通常处于关闭状态。如果出现问题,请将0<&1000 1>&1001 2>&1002更改为0<&1000 1>&1001 2>&1002 1000<&- 1001>&- 1002>&-

  • 您不能并行运行两个调试器。如果某些其他命令使用了/dev/tty(或STDIN),则也可能会出现问题。要解决此问题,请将/dev/tty替换为"${DEBUGTTY:-/dev/tty}"。在其他一些TTY中,键入tty; sleep inf,然后使用打印的TTY(即E。/dev/pts/60)进行调试,如DEBUGTTY=/dev/pts/60 debug command arg..所示。这就是外壳的力量,习惯它!

功能介绍:

  • 1000<&0 1001>&1 1002>&2移走了前三个FD
    • 这假设FD 1000、1001和1002是免费的
  • 0</dev/tty 1>/dev/tty 2>&0恢复前三个FD指向您当前的TTY。这样您就可以控制gdb
  • /usr/bin/gdb -q -nx -nw在外壳上运行gdb并调用gdb
  • -ex 'set exec-wrapper /bin/bash -c "exec 0<&1000 1>&1001 2>&1002 \"\$@\""创建一个启动包装程序,该程序将恢复保存到1000及以上的前3个FD。
  • -ex r使用exec-wrapper
  • 启动程序
  • --args "$@"传递给定的参数

那不容易吗?