cfunctionargumentsvariadic

Variadic function is behaving strangely


I am trying to understand what is wrong with my variadic function. For some reason it breaks all the variadic arguments, except the second and the third.

The function looks correct according to the documentation:
https://en.cppreference.com/w/c/language/variadic

I am using C standard 17, which is lower than 23.

Here is the C standard in CMake settings.

cmake_minimum_required(VERSION 3.25)
project(3 C)

set(CMAKE_C_STANDARD 17)

add_executable(${PROJECT_NAME} main.c)

The minimal working test, which shows the strangeness.

#include <stdarg.h>
#include <stdio.h>

void test(const char *fmt, ...) {
    va_list args;
    va_start(args, fmt);
    printf(fmt, args);
    va_end(args);
}

int main() {
    test("%d %d %d %d %d\n", (unsigned char) (1), (unsigned char) (2), (unsigned char) (3), (unsigned char) (4), (unsigned char) (5));
    return 0;
}

OS is Windows 10.
IDE is JetBrains CLion 2023.1.1.
Toolchain is selected as Visual Studio.
Compiler is Microsoft (R) C/C++ Optimizing Compiler Version 19.35.32216.1 for x64.
Architecture is 64-bit x86.

I see the following output of the test code:

1897200872 2 3 1 1077874749

So, only two arguments of five are correct. Other arguments are broken.

What am I doing wrong ?

Thank you.

UPDATE

OK. I have changed the printf to vprintf and now it prints the values correctly. But a new strangeness happens.

#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>

char *smprintf(const char *fmt, ...) {
    va_list args;
    va_start(args, fmt);
    int len = vsnprintf(NULL, 0, fmt, args);
    va_end(args);

    len++;
    char *buf = malloc(len);
    if (buf == NULL) {
        return NULL;
    }

    va_start(args, fmt);
    vsnprintf(buf, len, fmt, args);
    va_end(args);

    return buf;
}

void test(const char *fmt, ...) {
    va_list args;
    va_start(args, fmt);
    //vprintf(fmt, args);
    vprintf("Result: %s.\n", smprintf(fmt, args));
    va_end (args);
    //free(x);
}

int main() {
    test("%d %d %d %d %d\n", (unsigned char) (1), (unsigned char) (2), (unsigned char) (3), (unsigned char) (4), (unsigned char) (5));
    return 0;
}

Here, in the smprintf function, I am trying to make a formatted C string from the format and arguments.

Now the smprintf function breaks all the parameters for some reason.

Process finished with exit code -1073741819 (0xC0000005)

Solution

  • The updated working solution.

    #include <stdarg.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    char *smprintf(const char *fmt, va_list args) {
        va_list args3;
        va_copy(args3, args);
        int len = vsnprintf(NULL, 0, fmt, args3);
                va_end (args3);
        len++;
        char *buf = malloc(len);
        if (buf == NULL) {
            return NULL;
        }
        vsnprintf(buf, len, fmt, args);
        return buf;
    }
    
    void test(const char *fmt, ...) {
        va_list args;
                va_start(args, fmt);
        va_list args2;
        va_copy(args2, args);
        vprintf(fmt, args); // Debug.
        printf("\n"); // Debug.
                va_end (args);
        char *x = smprintf(fmt, args2);
        printf("Result: %s.\n", x);
        free(x);
                va_end (args2);
    }
    
    int main() {
        test("%d %d %d %d %d", (unsigned char) (1), (unsigned char) (2), (unsigned char) (3), (unsigned char) (4), (unsigned char) (5));
        return 0;
    }
    

    I am now able to create a formatted C string from the format and variadic arguments.