Я работаю над заданием по программированию, в котором меня просят написать код, способный прочитать команду из командной строки вместе с ее аргументом и выполнить программу с помощью команды execvp. Это мой код:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(int argc, const char * argv[]) {
char **cmd;
int i;
if (argc == 1){
fprintf(stdout, "No command inserted!\n");
exit(EXIT_SUCCESS);
}
cmd = (char **) malloc( argc * sizeof(char *));
cmd[0] = strdup(argv[1]);
if (argc > 2){
for (i = 1 ; i < argc - 1 ; i++ ){
cmd[i] = (char *) malloc( strlen(argv[i+1]) * sizeof(char) );
strcpy(cmd[i], argv[i+1]);
}
cmd[argc] = NULL;
execvp(cmd[0], cmd);
fprintf(stderr, "Failed Execution or not existing command!!\n");
exit(EXIT_FAILURE);
}
cmd[1] = NULL;
execvp(cmd[0], cmd);
fprintf(stderr, "Failed Execution or not existing command!!\n");
exit(EXIT_FAILURE);
return 0;
}
Код отлично работает, вводя команду без аргументов, например:
./a.out who
./a.out ls
но приводит к «Ошибке сегментации: 11» при написании таких команд, как:
./a.out ls -l
./a.out more file.txt
не могу понять где проблема...
cmd[i] = (char *) malloc( strlen(argv[i+1]) * sizeof(char) );
1) возвращаемый тип из функций распределения кучи (malloc, calloc, realloc) -void*
, который может быть назначен любому указателю. Приведение просто загромождает код (и подвержено ошибкам) 2) всегда проверяйте (!=NULL) возвращаемое значение, чтобы убедиться, что операция прошла успешно. 3) функцияstrlen()
возвращает индекс завершающему байту NUL, но индексы начинаются с 0, поэтому для получения правильной длины необходимо использовать+1
. (продолжение) - person user3629249   schedule 08.09.2017sizeof(char)
определено в стандарте C как 1. Умножение чего-либо на 1 не имеет абсолютно никакого эффекта. Таким образом, использование этого выражения просто загромождает код. - person user3629249   schedule 08.09.2017execvp()
обнаруживает ошибку и возвращается, она устанавливаетerrno
для указания причины ошибки. Поэтому лучше отображать соответствующее сообщение об ошибке. Таким образом, код может выиграть, заменив эту строку:fprintf(stderr, "Failed Execution or not existing command!!\n");
наperror( " execvp Failed Execution or not existing command!!\n");
, которая выведет в stderr заключенный текст, за которым следует сообщение о системной ошибке. - person user3629249   schedule 08.09.2017execvp( argv[1], argv+sizeof( char * ));
- person user3629249   schedule 08.09.2017execvp()
. Настоятельно рекомендуем: вызовитеfork()
, чтобы запустить новый процесс, затем в «дочернем» процессе вызовитеexecvp()
, а в родительском процессе вызовитеfree()
для каждой из областей, выделенныхmalloc()
. - person user3629249   schedule 08.09.2017