Warning C4840 in va_start

2

So far I had no problems with the code I attached in VS2015.    VS2017 shows me the following warning: warning C4840: non-portable use of the class' ATL :: CStringT > > as an argument of a variádica function and I do not guess why.    I tried to enclose flags in a (static_cast (flags)) but then things get worse. Can you think what the problem might be?

If you wonder why I do not use a variadic template the answer is because I have a lot of code written with va_start and changing routines that already work by different procedures can take me to unexpected results

void Entrada (CString flags, ...)
{
    CString   id;
    va_list   list;

    va_start(list, flags);
    id.FormatV (flags, list);
}

int main()
{
    int nRetCode = 0;

    HMODULE hModule = ::GetModuleHandle(nullptr);


    double   result;
    int      valor = 23;

    Entrada (_T("%s %lf %d"), _T("Texto"), -54.854, valor);

    return nRetCode;
}
    
asked by Josemi 29.07.2017 в 11:47
source

1 answer

0

The variadic engine inherited from C is a problematic beast, it does not offer type security, it is prone to errors, it opens security holes and it can cause more problems than it is capable of solving.

Variadic arguments to style C, work with copy of arguments (you can not pass references!), and undergo type transformations in a transparent way 1 : they are promoted to int the smaller types than the same (including enumerated types and bit fields) 2 , the same with the smaller types that double and ... what about complex C ++ objects ?.

Well, it depends. According to the C ++ standard in section 5.2.2.7 ( translation and highlighted mine):

  

5.2.2 Function calls

     
  • When there is no parameter for an argument provided, the argument is passed so that the receiving function can obtain the value of the argument by invoking va_arg [...] Standard conversions are applied to the expressions of the arguments a-rvalue, array-to-pointer and function-to-pointer. An argument whose type (possibly qualified constant or volatile) is std::nullptr_t will be converted to void* . After these conversions if the argument is not arithmetic, enumerated, pointer, pointer to member, or class, the program is malformed. Passing a potentially evaluated argument of type class having a non-trivial copy constructor, a non-trivial motion constructor, or a non-trivial destructor is conditionally supported with implementation-dependent semantics .
  •   

    Since the arguments of variádicas functions are copied , if a type whose construction or copy is used can have secondary effects (that is to say: it is not a trivial type), the compiler can decide not to give support to said operation.

    Can you think what the problem might be? Sure:

    In your case, it seems that VS2017 does support this operation, but since other compilers may decide not to support it, it warns you that your code might not work in other compilers (that is: it is not portable).

    1 That is to say: without control of the programmer and possibly without permission or knowledge of it.

    2 May cause unexpected conversions from unsigned to signed.

        
    answered by 31.07.2017 в 10:03