使用 gdb 调试 echo 程序时,K&R 对 echo 程序的解释令人困惑。怎么了?
K&R Explanation of echo program is confusing, when debugging it using gdb. What's wrong?
根据 K&R,他对 echo 程序的解释:
echo hello world
分别为 "By convention, argv[0] is the name by which the program was invoked, so argc is at least 1. If the argc is 1, there are no command-line arguments after the program name. In the example above, argc is 3, and argv[0], argv[1], and argv[2] are "echo"、"hello" 和 "world"。第一个可选参数是 argv[1],最后一个是 argv[argc-1]。"
但是,在使用 gdb 调试程序时,我可以看到以下内容:
(gdb) p argv[0]
= 0x7efff85a "/home/pi/new/a.out"
(gdb) p argv[1]
= 0x0
(gdb) p argv[2]
= 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]
= 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
= (char **) 0x7efff744
(gdb) p &**argv
= 0x7efff85a "/home/pi/new/a.out"
(gdb) p argv
= (char **) 0x7efff744
(gdb) p &argv
= (char ***) 0x7efff5e0
(gdb) p &argv[0]
= (char **) 0x7efff744
(gdb) p argv[0]
= 0x7efff85a "/home/pi/new/a.out"
片段 2:
(gdb) p argv[3]
= 0x7efffe5a "_=/usr/bin/gdb"
(gdb) p argv[4]
= 0x7efffe69 "LANG=en_GB.UTF-8"
(gdb) p &argv[3]
= (char **) 0x7efff754
问题:
• 片段 1:
- 我理解的对吗,
0x7efff85a
是字符串"/home/pi/new/a.out"
的十六进制值?如果是,它是如何获得的?换句话说,它是通过使用例如atoi()
函数获得的吗?
• 片段 3:
我理解的对吗,_=/usr/bin/gdb
转换成0x7efffe5a
?
此外,数组 argv 设置了一些预定义值,因为如果没有输入任何内容,它就在那里。我在哪里可以阅读有关此预定义值的信息?它是实现定义的吗?例如,在 windows 上,使用 Eclipse 或其他 IDE,它是否会为 argv[] 数组提供不同但预定义的值集?
代码段 1) 0x7efff85a
是指向此程序实例的字符串 "/home/pi/new/a.out"
的指针。
片段 2) 0x7efffe5a
是指向此特定实例的字符串 "_=/usr/bin/gdb"
的指针,但您不应依赖 argv[argc+1]
之后指向任何特定内容。
请注意 main
的完整定义是:
int main(int argc, char *argv[], char *envp[])
意思是在最后argv[]
后面跟着环境变量
您正在循环中修改 argv:
while (--argc>0)
printf("%s%s",*++argv,(argc>1)?" ":"");
所以观察之后不给你你想的!您正在溢出数组并访问环境数组...
要么在循环之前观察 argv,要么至少将其原始值存储在某个地方以便在之后观察它...因为您没有告诉我们您创建的确切(所有命令!)gdb 会话是什么,我们无法提供帮助你更进一步。
根据 K&R,他对 echo 程序的解释:
echo hello world
分别为 "By convention, argv[0] is the name by which the program was invoked, so argc is at least 1. If the argc is 1, there are no command-line arguments after the program name. In the example above, argc is 3, and argv[0], argv[1], and argv[2] are "echo"、"hello" 和 "world"。第一个可选参数是 argv[1],最后一个是 argv[argc-1]。"
但是,在使用 gdb 调试程序时,我可以看到以下内容:
(gdb) p argv[0]
= 0x7efff85a "/home/pi/new/a.out"
(gdb) p argv[1]
= 0x0
(gdb) p argv[2]
= 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]
= 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
= (char **) 0x7efff744
(gdb) p &**argv
= 0x7efff85a "/home/pi/new/a.out"
(gdb) p argv
= (char **) 0x7efff744
(gdb) p &argv
= (char ***) 0x7efff5e0
(gdb) p &argv[0]
= (char **) 0x7efff744
(gdb) p argv[0]
= 0x7efff85a "/home/pi/new/a.out"
片段 2:
(gdb) p argv[3]
= 0x7efffe5a "_=/usr/bin/gdb"
(gdb) p argv[4]
= 0x7efffe69 "LANG=en_GB.UTF-8"
(gdb) p &argv[3]
= (char **) 0x7efff754
问题:
• 片段 1:
- 我理解的对吗,
0x7efff85a
是字符串"/home/pi/new/a.out"
的十六进制值?如果是,它是如何获得的?换句话说,它是通过使用例如atoi()
函数获得的吗?
• 片段 3:
我理解的对吗,
_=/usr/bin/gdb
转换成0x7efffe5a
?此外,数组 argv 设置了一些预定义值,因为如果没有输入任何内容,它就在那里。我在哪里可以阅读有关此预定义值的信息?它是实现定义的吗?例如,在 windows 上,使用 Eclipse 或其他 IDE,它是否会为 argv[] 数组提供不同但预定义的值集?
代码段 1) 0x7efff85a
是指向此程序实例的字符串 "/home/pi/new/a.out"
的指针。
片段 2) 0x7efffe5a
是指向此特定实例的字符串 "_=/usr/bin/gdb"
的指针,但您不应依赖 argv[argc+1]
之后指向任何特定内容。
请注意 main
的完整定义是:
int main(int argc, char *argv[], char *envp[])
意思是在最后argv[]
后面跟着环境变量
您正在循环中修改 argv:
while (--argc>0)
printf("%s%s",*++argv,(argc>1)?" ":"");
所以观察之后不给你你想的!您正在溢出数组并访问环境数组...
要么在循环之前观察 argv,要么至少将其原始值存储在某个地方以便在之后观察它...因为您没有告诉我们您创建的确切(所有命令!)gdb 会话是什么,我们无法提供帮助你更进一步。