csegmentation-faultargv

C segmentation fault after altering argv


I want to change the values of argv in C, but I'm getting a segmentation fault. Here's the code.

#include <stdio.h>
#include <string.h>

int main(int argc, char **argv)
{
    for (int i = 1; argv[i]; i++)
    {
        char *val;

        printf("before: %d %s\n", i, argv[i]);
        argv[i] = "bar=foo";
        printf("after: %d %s\n", i, argv[i]);

        char *arg = argv[i];
        val = strchr(arg, '=');
        *val = '\0';
    }
    return 0;
}

I'm passing the argument foo=bar (and try to change it in line 11 to bar=foo). The output looks like this:

before: 1 foo=bar
after: 1 bar=foo

So, the modification actually takes place, but the line *val = '\0'; causes a segmentation fault.

Can somebody tell me why this is and how I can prevent it?


Solution

  • You make argv[i] point to a string literal, which is an array of read-only characters. Then you attempt to modify this read-only array leading to undefined behavior.

    There's a reason you should be using const char * for string literals.


    There are a couple of ways to solve your problem. The first and simplest, especially if you are going to use the same string for all arguments (not very likely except in a contrived examples such as the one you show) is to use an array, like char argument[] = "bar=foo";. Relying on the natural decay of arrays to pointers to their first arguments, you could use that in the assignment to argv[i] instead, and modify the array to your hearts content.

    But like I said that won't really be very useful except for simple examples. That leaves us with another option, using e.g. strdup to dynamically allocate and copy the strings (alternatively if strdup is not available, it's not a standard function, you could manually use malloc and strcpy). Since you then have dynamically allocated the memory it can also be modified to your hearts content. The problem here is that you then need to keep track of the original pointers and use free to free them again.

    So these are basically the two solutions you could use.One is unrealistic, and the other have dynamic memory allocations and all the problem that entails. There are really no good and especially no simple solutions to your problem.