You get the segmentation fault because you are using uninitialized pointers.
In other words: *(args+i)
is uninitialized.
Let's look at your memory:
char **args = malloc(argc * sizeof(char *));
This will give a local variable args
that points to a dynamic allocated memory area consisting of argc
pointers to char
. Looks like this:

But the argc
pointers to char are uninitialized (i.e. malloc
doesn't initialized anything) so the real picture is:

That is - the argc
pointers to char may point anywhere.
So when you do
strcpy(*(args+i), argv[i+1]);
^^^^^^^^^
Read uninitialized pointer
you read the i'th uninitialized pointer and copy the string at argv[i+1]
to that location. In other words - to a location that we can't know where is and most like doesn't belong to your program. This is likely to result in a seg fault.
So before you copy anything you want those char-pointers to point to some chars. Like:

So basically you need to do additional malloc
.
Now one problem is: How many chars do you need to malloc
?
Well, you can't know until you know the length of the input strings. So you need to put the malloc
inside the loop. Like:
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]);
}
}
Note:
You don't need to write sizeof(char)
as it is always 1
You have to add 1 to the string length of the input string in order to reserve memory for the string termination.
You should always check that malloc
doesn't return NULL
Instead of *(args+i)
you can use the more readable form args[i]
So after a real execution the picture could be:
