Почему я не могу использовать char **myargs вместо char *myargs[3] при вызове execvp()?

У меня есть программа C для создания дочернего процесса для запуска команды "wc exec.c".

Ниже представлена ​​программа.

/* Filename: exec.c*/

#include<stdio.h>
#include<sys/wait.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>

int main(int argc, char **argv)
{
    printf("Hello world (pid = %d).\n",(int) getpid());
    int ret = fork();
    if (ret < 0)
    {
            fprintf(stderr,"fork failed.\n");
            exit(1);
    }

    else if (ret == 0)
    {
            printf("I am the child process (pid = %d).\n",(int) getpid());

            // Launch command wc exec.c

            char *myargs[3];
            // char **myargs ;
            myargs[0] = "wc";
            myargs[1] = "exec.c";
            myargs[2] = NULL ;
            execvp(myargs[0], myargs);
            printf("Unreachable code\n");
    }

    else
    {
            int w = wait(NULL);
            printf("I am the parent of %d (pid = %d), w = %d\n", ret, (int) getpid(), w);
    }
    return 0;
}

Эта программа дает ожидаемый результат, так как дочерний процесс запускает "wc exec.c".

-bash-4.1$ ./a.out
Hello world (pid = 21362).
I am the child process (pid = 21363).
 45 115 789 exec.c
I am the parent of 21363 (pid = 21362), w = 21363
-bash-4.1$

Просто чтобы поиграть, я подумал об объявлении char *myargs[3] с помощью char **myargs . Теперь, когда я пытаюсь скомпилировать, gcc выдает предупреждение.

-bash-4.1$ gcc -Wall exec.c
exec.c: In function âmainâ:
exec.c:32: warning: âmyargsâ may be used uninitialized in this function
-bash-4.1$

строка 32 это строка

  myargs[0] = "wc";

Хотя я не мог понять значение этого предупреждения, слово «МОЖЕТ», использованное gcc, создало у меня впечатление, что «хорошо, gcc gcc считает, что оно МОЖЕТ быть использовано неинициализированным, но я инициализировал myargs[0] = «wc», поэтому, хотя МОЖЕТ быть проблемой, но проблемы нет».

Но когда я запускаю исполняемый файл, я вижу, что execvp() не выполняется (поскольку "wc exec.c") не выполняется.

-bash-4.1$ ./a.out
Hello world (pid = 21482).
I am the child process (pid = 21483).
I am the parent of 21483 (pid = 21482), w = 21483
-bash-4.1$

Я прочитал справочные страницы для execvp, и там говорится, что массив указателей (передается как второй аргумент для execvp()) должен заканчиваться указателем NULL. Я думал, что поскольку третий элемент char **myargs равен NULL, это удовлетворяет этому условию.

По какой причине char **myargs не работает вместо char *myargs[] в этом случае?

Спасибо.


person sps    schedule 17.02.2015    source источник
comment
Вам нужно, чтобы внешний указатель действительно указывал на что-то.   -  person Some programmer dude    schedule 17.02.2015


Ответы (1)


Потому что для этого нужно выделить место.

С участием

char *myargs[3];

вы автоматически выделяете место для 3 указателей char, так что у вас нет проблем, но когда вы это делаете

char **myargs;

у вас есть указатель на указатель char, поэтому, если вы никуда не укажете на него и попытаетесь получить к нему доступ, вы вызовете неопределенное поведение.

Чтобы использовать указатель на указатель char, вы можете сделать так, чтобы он указывал на допустимую память через malloc(), как это

myargs = malloc(3 * sizeof(*myargs));
if (myargs == NULL)
    doNotContinue_AllocationFailure();
myargs[0] = "some constant string";

и теперь код действителен.

Однако вы должны помнить, что указатель malloc()ed должен быть free()ed, когда он вам больше не нужен, для этого вам нужно сделать это

free(myargs);
person Iharob Al Asimi    schedule 17.02.2015
comment
Понимаю. Мое предположение заключалось в том, что когда я делаю myargs[0] = wc, то автоматически выделяется память, там хранится строка wc\0, а ее базовый адрес возвращается обратно в myargs[0]. (например, имя символа [] = имя). Вопрос о бесплатном (myargs): Где я буду это использовать? Потому что после выполнения execvp() образ процесса меняется, верно? Любой код после execvp() не будет выполняться? И если я поставлю free(myargs) внутри кода parent , то parent даже не узнает, что есть что-то вроде myargs ? - person sps; 17.02.2015
comment
кстати забыл подтвердить, что после использования malloc проблема решена!! - person sps; 17.02.2015
comment
@ 1Byn Я думаю, это должен быть новый вопрос. - person Iharob Al Asimi; 17.02.2015
comment
Скоро опубликую этот вопрос .. постараюсь сам что-то выяснить ... если я не смогу понять, спрошу, может быть, завтра .. - person sps; 17.02.2015