K&R 使用 gdb 调试时,echo 程序的解释令人困惑。怎么了?
Posted
技术标签:
【中文标题】K&R 使用 gdb 调试时,echo 程序的解释令人困惑。怎么了?【英文标题】:K&R Explanation of echo program is confusing, when debugging it using gdb. What's wrong? 【发布时间】:2019-07-07 03:59:28 【问题描述】:根据 K&R,他对 echo 程序的解释:
echo hello world
“按照惯例,argv[0] 是调用程序的名称,因此 argc 至少为 1。如果 argc 为 1,则程序名称后没有命令行参数。在上面的示例中,argc 是3、argv[0]、argv[1]、argv[2]分别是"echo"、"hello"、"world"。第一个可选参数是argv[1],最后一个是argv[argc- 1]。”
但是,在调试程序时,使用 gdb,我可以看到以下内容:
(gdb) p argv[0]
$2 = 0x7efff85a "/home/pi/new/a.out"
(gdb) p argv[1]
$3 = 0x0
(gdb) p argv[2]
$4 = 0x7efff86d "LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc"...
(gdb) p *argv[0]
$5 = 47 '/'
例 1:
#include <stdio.h>
int main(int argc, char *argv[])
int i;
while (--argc>0)
printf("%s%s",*++argv,(argc>1)?" ":"");
printf("\n");
return 0;
对于上面的代码示例,编译执行时如下:
pi@readonly:~/new$ cc -g echo.c
pi@readonly:~/new$ a.out hello world
hello world
使用 gdb 调试:
片段 1:
(gdb) p &*argv
$11 = (char **) 0x7efff744
(gdb) p &**argv
$12 = 0x7efff85a "/home/pi/new/a.out"
(gdb) p argv
$13 = (char **) 0x7efff744
(gdb) p &argv
$14 = (char ***) 0x7efff5e0
(gdb) p &argv[0]
$15 = (char **) 0x7efff744
(gdb) p argv[0]
$16 = 0x7efff85a "/home/pi/new/a.out"
片段 2:
(gdb) p argv[3]
$22 = 0x7efffe5a "_=/usr/bin/gdb"
(gdb) p argv[4]
$23 = 0x7efffe69 "LANG=en_GB.UTF-8"
(gdb) p &argv[3]
$24 = (char **) 0x7efff754
问题:
• 片段 1:
-
我理解正确吗,
0x7efff85a
是字符串"/home/pi/new/a.out"
的十六进制值?如果是,它是如何获得的?也就是说,是不是通过atoi()
等函数得到的?
• 片段 3:
我理解正确吗,_=/usr/bin/gdb
被转换为0x7efffe5a
?
此外,还有一些预定义的值被设置到数组 argv,因为万一没有输入任何内容,它就在那里。我在哪里可以阅读有关此预定义值的信息?它是实现定义的吗?例如,在 Windows 上,使用 Eclipse 或其他 IDE,它会为 argv[] 数组提供不同但预定义的值吗?
【问题讨论】:
不,它们是地址(指针)。查看您要打印的类型。 您需要在 GDB 中使用set args
命令来设置程序的命令行参数。
或在“运行”它时指定它们,即“运行你好世界”
argv[0]
是 /home/pi/new/a.out
是因为您没有将程序重命名为 echo
。虽然我必须承认 K&R 没有提到路径,或者可能是后来在 argv[0]
的定义中添加的。
如果argc
为1,则无法访问argv[2]
及以上。如果argc
为2 等,则无法访问argv[3]
。您从调试器获得的任何此类值都是没有意义的。
【参考方案1】:
片段 1) 0x7efff85a
是指向此程序实例的字符串 "/home/pi/new/a.out"
的指针。
片段 2) 0x7efffe5a
是指向此特定实例的字符串 "_=/usr/bin/gdb"
的指针,但您不应依赖 argv[argc+1]
之后指向任何特定内容。
【讨论】:
【参考方案2】:注意main
的完整定义是:
int main(int argc, char *argv[], char *envp[])
这意味着在最后一个 argv[]
之后跟随环境变量。
【讨论】:
实际上并不能保证是这个意思。但是你说得对,unix 的内部约定是 envp 指向的内存块紧跟 argv 指向的内存块。【参考方案3】:您正在循环中修改 argv:
while (--argc>0)
printf("%s%s",*++argv,(argc>1)?" ":"");
所以之后观察它不会给你你的想法!您正在溢出数组并访问环境数组...
要么在循环之前观察 argv,要么至少将其原始值存储在某个地方以在之后观察它...由于您没有告诉我们您创建的确切(所有命令!)gdb 会话是什么,我们无法进一步帮助您.
【讨论】:
以上是关于K&R 使用 gdb 调试时,echo 程序的解释令人困惑。怎么了?的主要内容,如果未能解决你的问题,请参考以下文章