2014-03-23 2 views
0

Функция execv принимает в качестве второго параметра массив указателей. У меня есть указатель на указатель, динамически созданный список строк.Как преобразовать char ** в char * [] в c?

Как создать массив указателей из этого?

char **list = malloc((argc)*sizeof(char*)); 
int i=0; 
for(i=0;i<argc;++i){ // using argv for example... 
list[i] = malloc(strlen(argv[i])+1); 
strcpy(list[i], argv[i]); 
} 
// create from list an array of pointers 
execv(list_pointers[0], list_pointers); 

В противном случае я получаю ошибку Bad адрес, если проходя просто list в execv.

+1

Как насчет использования '(char * []) ​​list_pointers' ?? –

+0

Я могу просто перечислить список? – user1561108

+0

Я не понимаю, почему это не сработает. Просто попробуйте ... –

ответ

1

Сигнатура функции execv объявлен в заголовке unistd.h является

int execv(const char *path, char *const argv[]); 

Пожалуйста, обратите внимание, что это то же самое, как

int execv(const char *path, char *const *argv); 

, что означает, что argv представляет собой указатель на объект типа char * const, то есть, постоянный указатель на символ. Кроме того, человек, страница execv говорит -

Первый аргумент, по соглашению, должен указать на имя , связанный с файлом, который выполняется. Массив указателей должен быть прерван указателем NULL.

Кроме того, list, тип которого char **, совместим по присваиванию со вторым аргументом execv. Я предлагаю внести следующие изменения:

// +1 for the terminating NULL pointer required for the 
// second argument of execv 

char **list = malloc((argc + 1) * sizeof *list); 
if(list == NULL) { 
    printf("not enough memory to allocate\n"); 
    // handle it 
} 
int i = 0; 
for(i = 0; i < argc; ++i) { 
    // strdup returns a pointer to a new string 
    // which is a duplicate of the string argv[i] 
    // this does effectively the same as the commented 
    // out block after the below statement. 
    // include the header string.h for the prototype 
    // of strdup POSIX function. 

    list[i] = strdup(argv[i]); 

    /* 
    list[i] = malloc(strlen(argv[i])+1); 
    if(list[i] == NULL) { 
     printf("not enough memory to allocate\n"); 
     // handle it 
    } 
    strcpy(list[i], argv[i]); 
    */ 
} 

list[argc] = NULL; // terminate the array with the NULL pointer 
execv(list[0], list); 
+0

Я добавил +1 в оператор malloc, но не назначил список [argc] NULL или добавил +1 к параметру execv 2nd, и он по-прежнему работал, как ожидалось. Это эквивалентно тому, что у вас есть, и если да, то почему? – user1561108

+2

@ user1561108 Я обновил свой ответ. Второй аргумент не должен содержать +1.Массив указателей, на который указывает второй аргумент 'execv', должен быть NULL-end else, иначе он будет вызывать неопределенное поведение. Я думаю, вам просто повезло, что он закончил NULL в случае, когда вы запускали программу. – ajay

+1

В системах, совместимых с POSIX, вы можете упростить тело цикла до 'list [i] = strdup (argv [i]);', функция 'strdup()' объединяет вызовы 'strlen()', 'malloc() 'и' strcpy() '. Также обратите внимание, что он только загромождает код для проверки возвращаемого значения 'malloc()': современные системы перекомпилируют свою память, поэтому 'malloc()' обычно всегда преуспевает, только когда вы получаете доступ к памяти, что ваш процесс может быть сбит ООМ-убийца. И проверка возвращаемого значения 'malloc()' не может защитить вас от этого. – cmaster

1

От execv человек страницы:

«Массив указателей должен заканчиваться указателем NULL.»

Функция execv не знает, подсчитывать аргумент

char **list = malloc((argc+1)*sizeof(char*)); 
if (list == NULL) { 
    abort(); 
} 
int i; 
for(i=0;i<argc;++i){ // using argv for example... 
    if ((list[i] = strdup(argv[i])) == NULL) { 
     abort(); 
    } 
} 
list[argc] = NULL; 
execv(list[0], list); 

EDIT I также удаляется список + 1 из вызова execv, спасибо за @ajay его нахождения

Смежные вопросы