Search code examples
cmallocdynamic-memory-allocationrealloc

Realloc() Behavior


I am trying to concatenate multiple arguments passed via argv[] into a c-string. I'm not using a char array because I do not want any limits on the amount of characters passed through argv[].

This is an example of how I would execute my program.

executable -cmd rotn 13 Hello World

char *externalCommand = NULL;
    if (argc >= 3 && strcmp(argv[1], "-cmd") == 0)
        {
            externalCommand = (char *)malloc(sizeof(char) * (strlen(argv[2]) + 1));
            strcpy(externalCommand, argv[2]);
            for (int i = 3; i < argc; ++i)
            {
                int textLength = strlen(externalCommand);
                externalCommand = (char *)realloc(externalCommand, sizeof(char) * (textLength + 1));
                strcpy(externalCommand + textLength, " ");
                strcpy(externalCommand + textLength + 1, argv[i]);
            }
        }

My goal is to end of with the string "externalCommand" to be equal : "rotn 13 Hello World" When I go through the for loop for the first time, externalCommand is "rotn 13", which is normal.

When I go through the loop a second time, I get weird behaviour when I run realloc(). externalCommand becomes "rotn ÍÍÍýýýý««««««««îþîþ". I understand that these are garbage values, but I don't understand why realloc() overwrites the number "13" from my string.

To solve the issue, I can replace :

externalCommand = (char *)realloc(externalCommand, sizeof(char) * (textLength + 1));

with :

externalCommand = (char *)realloc(externalCommand, sizeof(char) * (textLength + 3));

which doesn't overwrite the value 13.

I would like to understand why do I need to add 3 to the textLength when reallocating.


Solution

  • Your realloc() is not allocating enough memory to hold the data you are copying into the buffer. Use this instead:

    externalCommand = (char *)realloc(externalCommand, sizeof(char) * (textLength + 1 + strlen(argv[i]) + 1));
    

    That being said, if you precalculate the buffer size, you can get rid of realloc() and use a single malloc():

    char *externalCommand = NULL;
    if (argc >= 3 && strcmp(argv[1], "-cmd") == 0)
    {
        int textlength = strlen(argv[2]);
        for (int i = 3; i < argc; ++i)
            textLength += (1 + strlen(argv[i]));
    
        externalCommand = (char *)malloc(sizeof(char) * (textLength + 1));
    
        strcpy(externalCommand, argv[2]);
        for (int i = 3; i < argc; ++i)
        {
            strcat(externalCommand, " ");
            strcat(externalCommand, argv[i]);
        }
    }