<< PreviousNext >>

Answer to Exploring function calls

The reason for this lies in how calling conventions are implemented. On x86 systems, the standard one is cdecl, partly because it supports variable number of arguments. In cdecl, the caller allocates the parameters on the stack, and it is the callers responsibility to clean up the stack later on. This is good since the caller is then able to pass any number of parameters to a function, and the called function does not have to know exactly how many since it is not in charge of cleaning up the stack anyway.

This changed with C++. C++ brought destructors into the picture. Initially I thought that since cdecl specifies that the caller is responsible for cleaning up the stack, the caller would also be responsible for destroying any objects that were passed on the stack as well. It turns out this is not the case. Instead the called function runs the destructor on the parameters, and then the caller frees the memory from the stack. This means that we have actually lost the ability of variable parameter lists (until C++11 re-introduced them) in C++. Yet they are used. How does this work?

It turns out that this is the reason (i guess) why GCC disallows passing other types than "trivially copyable" types into variable argument lists. If it would allow that, then it would not be possible to run the correct destructor on the object later on, which would violate the guarantee of the destructor being called exactly once (unless these calls were treated specially, of course). Visual Studio has taken another approach instead. That compiler will silently pass a reference to the object instead ("easily" seen if you read the disassembly output from the compiler ☺). The va_arg macro correctly handles this, but we avoid one copy and lose the by-value semantics.

The solution for GCC would therefore be to pass the parameters by pointer (or reference), and by that we would get the same behaviour there as well.

Problem

Comments

New comment

You can use GitHub flavored markdown here. Parsed by Parsedown, which does not support all of GitHub's features. For example, specifying the language of code listings is not supported.

Name: