为啥 GDB 会启动一个新的 shell 以及如何禁用这种行为?

Posted

技术标签:

【中文标题】为啥 GDB 会启动一个新的 shell 以及如何禁用这种行为?【英文标题】:Why does GDB start a new shell and how to disable this behaviour?为什么 GDB 会启动一个新的 shell 以及如何禁用这种行为? 【发布时间】:2012-02-11 06:34:10 【问题描述】:

我正在解决一个问题,即从 GDB 启动应用程序会导致符号查找错误,但从 shell 启动它可以正常工作。

事实证明,无论何时你从 GDB 中启动一个程序,它都会启动一个新的 shell,从而覆盖我在启动 GDB 之前设置的所有环境变量(如 LD_LIBRARY_PATH)。

这不是我真正想要的行为。有人可以解释这背后的理由,或者告诉我如何关闭它吗?

【问题讨论】:

【参考方案1】:

我猜你无条件地在你的~/.cshrc 等中设置了LD_LIBRARY_PATH。因此,如果您在 shell 提示下执行以下操作:

export LD_LIBRARY_PATH=foo  # or for csh:
setenv LD_LIBRARY_PATH foo
$SHELL -c 'echo $LD_LIBRARY_PATH'

结果不是foo。不要这样做那个

这通常发生在 CSH 用户身上,他们忽略了保护他们的 ~/.cshrc 免受非交互式 shell 的攻击。设置BASH_ENV 的 BASH 用户也可能发生这种情况。

【讨论】:

我刚刚在我的配置中遇到了这个确切的错误。【参考方案2】:

我遇到了同样的问题。我在inferior.h中找到了(gdb的源代码gdb/inferior.h) 有一个宏STARTUP_WITH_SHELL,还有一条评论为

/* If STARTUP_WITH_SHELL is set, GDB's "run"
   will attempts to start up the debugee under a shell.
   This is in order for argument-expansion to occur. E.g.,
   (gdb) run *
   The "*" gets expanded by the shell into a list of files.
   While this is a nice feature, it turns out to interact badly
   with some of the catch-fork/catch-exec features we have added.
   In particular, if the shell does any fork/exec's before
   the exec of the target program, that can confuse GDB.
   To disable this feature, set STARTUP_WITH_SHELL to 0.
   To enable this feature, set STARTUP_WITH_SHELL to 1.
   The catch-exec traps expected during start-up will
   be 1 if target is not started up with a shell, 2 if it is.
   - RT
   If you disable this, you need to decrement
   START_INFERIOR_TRAPS_EXPECTED in tm.h. */
#define STARTUP_WITH_SHELL 1
#if !defined(START_INFERIOR_TRAPS_EXPECTED)
#define START_INFERIOR_TRAPS_EXPECTED   2
#endif

然后我将 STARTUP_WITH_SHELL 设置为 0 并递减 START_INFERIOR_TRAPS_EXPECTED 并重新编译了我的 gdb。之后 gdb 不再从 shell 启动。

【讨论】:

当前 gdb 允许您通过以下方式进行操作:set startup-with-shell off【参考方案3】:

当您从 shell 启动 gdb 时,您将它作为一个新进程启动,这是没有办法的。在 Unix 中,新进程继承了父进程的一些环境。

为确保变量被继承,如果您使用的是类似 bourne 的 shell,请尝试将其导出:

export LD_LIBRARY_PATH=...

【讨论】:

我猜问题是 OP 将他的 LD_LIBRARY_PATH 设置为 ~/.bashrc 或类似的东西,并且该设置 覆盖 他在调用 GDB 之前设置的任何内容,] . 你成功了,@EmployedRussian !【参考方案4】:

调试对象(gdb 用语中的inferior)总是从干净的环境开始,以便获得更多可重现的结果。为了在那里设置一个变量,使用

set env VARNAME=VALUE

运行前的命令。

【讨论】:

如果你所说的“干净的环境”指的不是 GDB 自身环境的副本(加上已经执行的任何 set env 命令),那么你就大错特错了。

以上是关于为啥 GDB 会启动一个新的 shell 以及如何禁用这种行为?的主要内容,如果未能解决你的问题,请参考以下文章

GDB怎么调试使用.sh(shell脚本)启动的程序?(未完成,待测试)

GDB怎么调试使用.sh(shell脚本)启动的程序?(未完成,待测试)

如何从外部分离 gdb 会话?

Linux系统中GDB调试详细操作方法

如何在 Python 中生成一个新的独立进程

为啥我在启动一个新的 Django 项目时会收到​​“ImportError: cannot import name find_spec”?