K & R Объяснение echo-программы сбивает с толку, когда отлаживаете ее с помощью gdb.В чем дело? - PullRequest
0 голосов
/ 13 февраля 2019

Согласно K & R, его объяснение эхо-программы: 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:

  1. Правильно ли я понимаю, что 0x7efff85a это шестнадцатеричное значение строки "/home/pi/new/a.out"?Если да, то как это было получено?Другими словами, получено ли это, например, с помощью функции atoi()?

• Фрагмент 3:

Правильно ли я понимаю, что _=/usr/bin/gdb преобразуется в 0x7efffe5a?

Кроме того, есть некоторые предопределенные значения, установленные для массива argv,потому что, в случае, если ничего не было введено, оно есть.Где я могу прочитать об этих предопределенных значениях?Это определяется реализацией?Например, в Windows, с использованием Eclipse или других IDE, будет ли он давать другие, но предопределенные значения, установленные также для массива argv []?

Ответы [ 3 ]

0 голосов
/ 13 февраля 2019

Обратите внимание, что полное определение main:

int main(int argc, char *argv[], char *envp[])

Это означает, что после последнего argv[] следуют переменные среды.

0 голосов
/ 13 февраля 2019

Вы изменяете argv в цикле:

while (--argc>0)
        printf("%s%s",*++argv,(argc>1)?" ":"");

, чтобы наблюдение за ним не давало вам того, что вы думаете!Вы переполняете массив и получаете доступ к массиву окружения ...

Либо наблюдайте argv перед циклом, либо хотя бы сохраняйте его первоначальное значение где-нибудь, чтобы наблюдать его после ... Так как вы не сказали нам, что былоТочный (все команды!) сеанс GDB, который вы сделали, мы не можем вам помочь.

0 голосов
/ 13 февраля 2019

Фрагмент 1) 0x7efff85a - указатель на строку "/home/pi/new/a.out" для этого экземпляра программы.

Фрагмент 2) 0x7efffe5a - указатель на строку "_=/usr/bin/gdb" для этого конкретного экземпляра, но вы не должны полагаться на argv[argc+1] и далее, указывающие на что-то конкретное.

...