Krypton
Krypton

Reputation: 3325

Weird behavior of vsprintf

I have been pulling my hair out because of this 1 line of code. If I don't dynamically allocate memory for the extra (by just having char extra[*cur_size+1];), vsprintf got stuck.

char *append(char *str, int *cur_size, char *fmt, ...) {
    va_list args;
    va_start(args, fmt);
    int len = vsnprintf(NULL, 0, fmt, args) + strlen(str);
    if (len > *cur_size) {
        //alloc more memory
        *cur_size = len * sizeof (char) << 1;
        char *extra = malloc(*cur_size+1);
        // char extra[*cur_size+1]; will cause problem
        strcpy(extra, str);
        str = extra;
    }
    vsprintf(eos(str), fmt, args);
    va_end(args);
    LOGE("len = %d, cur_size = %d", len, *cur_size);
    return str;
}

Upvotes: 0

Views: 178

Answers (2)

unwind
unwind

Reputation: 399979

The array goes out of scope and becomes invalid to access through the aliased pointer str, which is why that solution won't work.

Your actual solution is broken too, though: it leaks the memory passed in by the caller in str, since that pointer just gets overwritten with the newly allocated memory extra.

If your function is expecting a dynamically allocated pointer in str, you should free() it before overwriting the pointer with extra. You might also want to look at realloc(), if so remember that the return value of realloc() might be a new pointer, so keep your current solution where str is returned by the function.

Upvotes: 2

hmjd
hmjd

Reputation: 122001

If you use:

char extra[*cur_size + 1];

the array will be out of scope at the next }, meaning str will be a dangling pointer. When you use malloc() the memory outlives the scope.

Upvotes: 2

Related Questions