Вы получаете ошибку сегментации, потому что используете неинициализированные указатели.
Другими словами: *(args+i)
неинициализирован.
Давайте посмотрим на вашу память:
char **args = malloc(argc * sizeof(char *));
Это даст локальную переменную args
, которая указывает на динамически выделенную область памяти c, состоящую из argc
указателей на char
. Выглядит так:
Но указатели на argc
на символ не инициализированы (т.е. malloc
ничего не инициализирует), поэтому реальная картина это:
То есть - argc
указатели на char могут указывать куда угодно.
Поэтому, когда вы делаете
strcpy(*(args+i), argv[i+1]);
^^^^^^^^^
Read uninitialized pointer
Вы читаете i-й неинициализированный указатель и копируете строку в argv[i+1]
в это место. Другими словами - в место, которое мы не можем знать, где находится и которое больше всего нравится, не принадлежит вашей программе. Это может привести к ошибке сегмента.
Поэтому, прежде чем копировать что-либо, вы хотите, чтобы эти хар-указатели указывали на некоторые символы. Как:
Так что в основном вам нужно сделать дополнительные malloc
.
Теперь одна проблема: сколько у вас символов нужно malloc
?
Ну, вы не можете знать, пока не узнаете длину входных строк. Поэтому вам нужно поместить malloc
внутрь l oop. Как:
int main (int argc, char * argv[]) {
char **args = malloc(argc * sizeof(char *));
for (int i = 0; i < argc - 1; ++i) {
*(args+i) = malloc(strlen(argv[i+1]) + 1); // Allocate memory
strcpy(*(args+i), argv[i+1]);
}
}
Примечание:
Вам не нужно писать sizeof(char)
, как всегда 1
Вы должны добавить 1 к длине строки входной строки, чтобы зарезервировать память для завершения строки.
Вы должны всегда проверять, что malloc
не возвращает NULL
Вместо *(args+i)
вы можете использовать более читаемую форму args[i]
Таким образом, после реального выполнения картина может быть: