我的电脑运行 Ubuntu 14.04。GDB在不同的账户中似乎异常。例如我做了一个非常简单的测试。我在下面写了一个文件~/test/test.c:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
printf("hello,world");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
并使用命令"gcc -g test.c -o test"构建,然后我得到名为 test 的结果文件。下一步,运行 gdb 进行调试。请注意,当前帐户是我自己的用户。
$gdb test
(gdb)l //work well
(gdb) b 6 //work well
(gdb) r //error: Cannot exec /home/xxx/test/test -c exec /home/xxx/test/test .
//Error: No such file or directory
Run Code Online (Sandbox Code Playgroud)
但是如果我通过命令“su”更改为 root 帐户,gdb 运行良好。为什么?
看来您的 SHELL 变量设置为不存在的文件。请尝试以下操作:
export SHELL=/bin/sh
gdb test
Run Code Online (Sandbox Code Playgroud)
确保/bin/sh存在且可执行。这su不是因为 root 权限,而是因为su重置了SHELL环境变量。根据su 手册页:
请注意,环境的默认行为如下:
$HOME、$SHELL、$USER、$LOGNAME、$PATH 和 $IFS 环境变量被重置。
如果您问自己,“我怎么会从以下错误消息中知道这一点?”:
//error: Cannot exec /home/xxx/test/test -c exec /home/xxx/test/test .
//Error: No such file or directory
Run Code Online (Sandbox Code Playgroud)
你不是一个人。这似乎是来自gdb. 当gdb决定需要使用 shell 执行您的命令时,它会按以下格式构造命令:
/path/to/shell -c exec /path/to/executable
Run Code Online (Sandbox Code Playgroud)
但是,当它打印错误消息时,它会执行以下操作:
save_errno = errno;
fprintf_unfiltered (gdb_stderr, "Cannot exec %s", exec_file);
for (i = 1; argv[i] != NULL; i++)
fprintf_unfiltered (gdb_stderr, " %s", argv[i]);
fprintf_unfiltered (gdb_stderr, ".\n");
fprintf_unfiltered (gdb_stderr, "Error: %s\n",
safe_strerror (save_errno));
gdb_flush (gdb_stderr);
Run Code Online (Sandbox Code Playgroud)
这exec_file是您在命令行上传递的文件的扩展路径。它exec_file首先打印,然后是 的元素argv,从第一个索引开始。 argv包含它传递给的参数execvp。
不幸的是,它尝试使用的外壳位于 的第 0 个元素中argv,它永远不会被打印出来。因此,您永远不会看到execvp找不到的文件。
此外,它然后打印一个尾随.,它实际上不是它传递给的参数之一,execvp并且可能在那里使消息成为一个完整的句子。
最后,它打印我们从调用 中得到的错误execvp,即找不到可执行文件。
这个错误很可能是由于这个错误处理代码对于gdb尝试直接执行命令的情况和使用 shell的情况是相同的。在前一种情况下,构造的错误消息看起来是正确的,exec_file并且argv[0]是相同的。