Кто сказал вам, что вы «не может выделить другой options[i]
и установить его в NULL» было неправильно. Это именно то, что вы делаете.
Однако, у вас есть ошибки в коде, и ошибки свидетельствуют о том, что вы не понимаете, что это означает для «выделить еще один options[i]
.»
char (*options)[MAXLEN]; /* This is wrong */
char *ptr;
ptr = strtok(input, " \r\n");
if(!ptr)
continue;
int i = 0;
optionen = malloc(sizeof(*options));
if(!options)
die("malloc");
while(ptr){
if(i > 0){
options = realloc(options, (i+1)*sizeof(*options));
if(!options)
die("malloc");
}
strcpy(options[i], ptr); /* This is also wrong */
if(!options[i])
die("strcpy");
ptr = strtok(NULL, " \r\n");
i++;
}
Во-первых, char (*options)[MAXLEN]
неправильный тип массива и запись в него не может быть установлен в NULL. Вам нужно вместо этого char **options
.
Второе, realloc
Операция, которую вы уже делаете, фактически выделяет больше options[i]
слотов. Но вам также необходимо выделить пространство для самих строк (но не для NULL). Вы делаете это с strdup
.
options[i] = strdup(ptr); /* Instead of the "also wrong" line */
(в зависимости от того, что input
, вы могли бы быть в состоянии уйти только с помощью строки указатели strtok
возвращается, но не видя больше кода я не могу быть уверен, что это безопасно.)
И затем, после цикла, вы просто устанавливаете окончательный слот options[i]
в NULL, и все готово.
Я бы структурировать петлю немного по-другому, например:
char **options;
char *ptr;
size_t i, asize;
ptr = strtok(input, " \t\r\n");
if (!ptr) continue;
options = 0;
i = 0;
asize = 2;
do {
while (i >= asize) {
asize *= 2;
options = xreallocarray(options, asize, sizeof(char *));
}
options[i++] = xstrdup(ptr);
ptr = strtok(0, " \t\r\n");
} while (ptr);
while (i >= asize) {
asize *= 2;
options = xreallocarray(options, asize, sizeof(char *));
}
options[i] = 0;
execve(options[0], options, environ);
die("execve");
Функция xreallocarray
и xstrdup
являются нестандартными, но они должны быть в вашей сумке простых функций, которые вы добавляете к каждой программе, что вы пишете , Вот их определения. Они используют функцию die(), которая у вас уже есть.
void *
xreallocarray(void *optr, size_t nmemb, size_t size)
{
/* s1*s2 <= SIZE_MAX if both s1 < K and s2 < K where K = sqrt(SIZE_MAX+1) */
const size_t MUL_NO_OVERFLOW = ((size_t)1) << (sizeof(size_t) * 4);
if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
nmemb > 0 && SIZE_MAX/nmemb < size) {
errno = ENOMEM;
die("malloc");
}
void *rv = realloc(optr, size * nmemb);
if (!rv)
die("malloc");
return rv;
}
char *
xstrdup(const char *s)
{
size_t n = strlen(s) + 1;
char *rv = malloc(n);
if (!rv)
die("malloc");
memcpy(rv, s, n);
return rv;
}
Не верьте тому, что они сказали. Выделите другую запись и установите ее значение «NULL». –
Можете ли вы дать мне пример строки, как это сделать? –
Правильно ли я читаю и правильно разбираю, что в 'char (* options) [MAXLEN];', 'options' является указателем на массив символов MAXLEN? Это намерение? –