Никогда возвращает указатель на локальную переменную обратно в вызывающую функцию.
char in[70];
/* ... */
tok_inline = strtok(in," ");
int i;
for(i=0; i < NUMBEROFARGUMENTS; i++){
input[i] = tok_inline;
/* ... */
Возвращаемое значение strtok
является указателем на позицию внутри in
, а не копией или чем-то в этом роде. Поскольку in
выделяется в стеке, а не динамически с использованием malloc
, он и эти указатели больше не будут действительными, когда вернется check_input
и кадр стека будет уничтожен.
Сохранение указателя на любую из этих переменных, которые больше не существуют, приведет к неопределенному поведению. Как вы заметили, когда эта позиция в стеке повторно используется для чего-либо еще (других переменных, вызовов функций и т. Д.), Ваши (недопустимые) строки будут испорчены.
Альтернативой является использование strdup
на tok_inline
, в котором malloc
используется для создания дубликата строки.
РЕДАКТИРОВАТЬ: Вы также должны проверять возвращаемое значение strtok
(то есть. tok_inline
) в состоянии вашего for
цикла, и завершаться также, если возвращается NULL
это означает, что токенов больше нет.
Измените свою подпись цикла for
на: for(i=0; i < NUMBEROFARGUMENTS && tok_inline; i++)
.
Кроме того, рассмотрите возможность использования fgets(in, 70, stdin);
вместо gets
, который небезопасен и может вызвать переполнение буфера, если размер ввода больше, чем размер вашего буфера. Также обратите внимание, что символ новой строки '\n'
сохраняется в конце буфера, если он подходит.
EDIT2: Кроме того, второй аргумент (argv
), переданный в execvp
, представляет собой массив строк с окончанием NULL
, т.е. {"ls", NULL }
. Для этого:
- Добавить
input[i] = NULL;
после цикла for
в check_input
- Измените
char* input[NUMBEROFARGUMENTS];
на char* input[NUMBEROFARGUMENTS + 1];
, чтобы у вас был еще 1 элемент в массиве для NULL
.
Также, если вы решите использовать fgets
, вам нужно будет удалить '\n'
из конца буфера (если он существует). Ваша функция check_input
может выглядеть примерно так:
void check_input(char** input){
char in[70];
char *tok_inline;
size_t len;
fgets(in, 70, stdin);
len = strlen(in);
if (in[len - 1] == '\n')
in[len - 1] = '\0';
tok_inline = strtok(in," ");
int i;
for(i=0; i < NUMBEROFARGUMENTS && tok_inline; i++){
input[i] = strdup(tok_inline);
tok_inline = strtok(NULL," ");
}
input[i] = NULL;
}
EDIT3: Что касается вашего последнего запроса об утечках памяти, да, вы должны освободить память. Вам не нужно в дочернем процессе, так как при вызове exec
этот процесс будет заменен новым процессом.
Однако вы должны освободить память, выделенную родителем. Поскольку мы NULL
завершили наш массив, просто добавьте следующее в любое место в блоке else
execute
:
while (*input)
free(*input);