使用 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:

  1. 我理解的对吗,0x7efff85a是字符串"/home/pi/new/a.out"的十六进制值?如果是,它是如何获得的?换句话说,它是通过使用例如atoi()函数获得的吗?

• 片段 3:

  1. 我理解的对吗,_=/usr/bin/gdb转换成0x7efffe5a

  2. 此外,数组 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 会话是什么,我们无法提供帮助你更进一步。