On 07/23/2017 10:30 PM, jacobnavia wrote:
> Le 20/07/2017 à 16:52, Manfred a écrit :
>> On 7/19/2017 10:44 PM, Ian Collins wrote:
>>> The args parameter *is* passed by value!
>> This is not always the case. x86_64 defines it as an array of length
>> 1, which is passed by reference (I learned it the hard way)
>
> There are two issues here:
>
> 1: Try to distinguish between args that have the default value and args
> that were passed by the calling function.
> 2: How the actual variable arguments stuff is passed in the x86-64.
I am not sure how much I can help, but I am trying to start with a
couple of preliminary considerations here.
- va_list in C++ is no better, no worst than it is in C. It has been
inherited as-is by Bjarne as part of C compatibility. Its usage is also
the same as in C (I think the constructor does not really add much, as
long as you can't have additional operations)
The official way introduced to handle variable arguments in C++ is
variadic templates. This is definitely more robust than va_list, but
unfortunately it is not compatible at all with it (i.e. it requires
substantial code rewriting).
- The way I see it, va_list is meant to be used as an opaque type, only
to be accessed via va_start, va_arg, va_end and va_copy (where
available) - I mean, other than that you give up with portability, I
believe.
As far as I can understand, the problem you are having right now arises
for not having handled va_list as opaque in the first place, and so
changing achitecture resulted in the current problem.
This is to say that, possibly, one hint would be to try to solve the
portability problem where it arises, i.e. get rid of the = default
void SetErrorN(ErrorCode ec, int mc,
const char* emf = NULL, va_list args /* = NULL */);
This breaks the code as it is now, but it makes it possible to identify
where such default is used, and replace it instead with a properly
initialized va_list - via va_start. I don't know how much feasible this
is in your case.
You would still be left with the doubt whether args is empty of not, but
this is in fact how va_list works as per standard, correct me if I am
wrong (it is one of its limitations). In C (as well as in C++) it is the
responsibility of the programmer to ensure that the callee does not
exceed the amount of arguments provided.
If this was not done in the beginning, it could be an additional problem.
If this is not possible, the second alternative would probably be using
va_list*, and use address comparison as identity check, or you can use a
NULL va_list* when empty.
cppreference.com says: "It is legal to pass a pointer to a va_list
object to another function and then use that object after the function
returns."
http://en.cppreference.com/w/cpp/utility/variadic/va_list
I would not go down the path of issue 2. It looks that you have
considerably more experience than I have, but even if you solve entirely
issue 2, you get to a solution that is not portable, so the problem is
likely to show up again with the next architecture.
Hope this helps..