1
votes

Main data is three double defined in the main. A variadic function, wrapperVariadic, take them and return true iff sum of them is strictly positiv. Given numbers are all small and positiv, so the result must be true.
wrapperVariadic call summerVariadic for get sum of all numbers.
summerVariadic put each number in a double std::vector, then call summerNonVariadic for compute sum of all numbers contained in the vector.

Problem : va_args in summerVariadic are always zero. When use valgrind on final executable, it detects "Conditional jump or move depends of unitialized value(s)" in main. According to --track-origin=yes option, origin of this is Uninitialised value was created by a stack allocation.

The three functions used :

// simple vector summer
float summerNonVariadic(const std::vector<double> values) {
        float sum = 0.;
        for(unsigned int summed = 0; summed < values.size(); summed++) {
                sum += values[summed];
        }
        return sum; 
}



// put the n doubles in a vector, and call summerNonVariadic.
float summerVariadic(const unsigned int n, ...) {
        std::vector<double> values;
        va_list args;
        va_start(args, n); 

        for(unsigned int j = 0; j < n; j++) {
                values.push_back(va_arg(args, double));
                //printf("AIG:%f\n", values.back());
                // printf call show that pushed values are always equal to zero,
                // and generates lots of "Conditional jump" valgrind error
        }

        va_end(args);
        return summerNonVariadic(values); 
}



// the wrapper
bool wrapperVariadic(const unsigned int n, ...) {
        va_list args;
        va_start(args, n); 
        float summer_said = summerVariadic(n, args);
        va_end(args);
        return summer_said > 0; 
}

A macro for runtime following:

#define LOGOK fprintf(stderr,"OK:%s:%u\n", __FILE__, __LINE__);

The main function, in main.cpp :

int main(int argc, char* argv[]) {
        double a = 4.2, b = 5.1, c = 0.3;
        bool bool_res = wrapperVariadic(3, a, b, c);
        LOGOK // line 125
        if(bool_res) {
                LOGOK // line 127, never reached
        }
        LOGOK // line 129

        return EXIT_SUCCESS;
}

Call valgrind:

valgrind --leak-check=full --track-origins=yes  ./a.out

Final Output:

==8624== Memcheck, a memory error detector
==8624== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==8624== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==8624== Command: ./a.out
==8624== 
OK:main.cpp:125
==8624== Conditional jump or move depends on uninitialised value(s)
==8624==    at 0x40B9AD: main (main.cpp:126)
==8624== 
OK:main.cpp:129
==8624== 
==8624== HEAP SUMMARY:
==8624==     in use at exit: 0 bytes in 0 blocks
==8624==   total heap usage: 4 allocs, 4 frees, 80 bytes allocated
==8624== 
==8624== All heap blocks were freed -- no leaks are possible
==8624== 
==8624== For counts of detected and suppressed errors, rerun with: -v
==8624== Use --track-origins=yes to see where uninitialised values come from
==8624== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)

We can see that final value is false, because of bad reading of double values of the vector in summerNonVariadic.

Replace line 124 in main by double bool_res = summerVariadic(3, a, b, c); remove all error and generate expected result. (OK:main.cpp:127)

What is the problem with this chained variadic function call ?

versions:

gcc version 4.7.2 (Debian 4.7.2-5)
1
I don't see any line numbers in the valgrind output, are you compiling with -g ? if so, what line is the jump occurring on?Ryan Haining
@RyanHaining There is no line showed in valgrind output. The jump occurying at line 126 of main, at if(bool_res) {. bool_res appear as an unitialized value. I will update post with using of -g flag.aluriak

1 Answers

4
votes

As you use summerVariadic(n, args);, you have to provide float summerVariadic(const unsigned int n, va_list args).

Since C++11, you may use variadic template instead:

template<typename ... Ts>
float summerVariadic(Ts... args) {
    return summerNonVariadic({args...}); 
}