|
|
Classification: |
C++ |
Category: |
Debugging |
Created: |
01/13/2005 |
Modified: |
01/13/2005 |
Number: |
FAQ-1207 |
Platform: |
Symbian OS v8.1b, Symbian OS v9.0 |
|
Question: I've got code using "..." and VA_LIST, and it's worked fine with Developer Studio, CodeWarrior and GCC. When I compile it
using the RealView compiler, the code stops working.
Answer: The change in behaviour may be due to the change in representation of VA_LIST.For most of the older compilers, Symbian generically defines VA_LIST to be
typedef TInt8 *VA_LIST[1];
The change in behaviour may be due to the change in representation of VA_LIST. For newer compilers complying to the ARM Base Platfrom ABI, the definition is:
typedef struct __va_list { void *__ap; } va_list;
These definitions have a different implications for code which passes VA_LIST objects around: the old definition is effectively
equivalent to a reference, but the new definition is an object which can be copied and passed by value. This shows up in code
like this:
int DoNextArg(char*& aFmt, VA_LIST aList) { // code which finds and decodes at the next % thing in aFmt aFmt = new_ptr; char* arg = VA_ARG(aList, char*); if (arg == 0) return 0; // end of list // more code ... return 1; }
int MyPrintf(const char* aFmt, ...) const { VA_LIST list; VA_START(list, aPath); char* fmt = aFmt; int argCount=0;
while (DoNextArg(fmt, list)) { argCount++; }
VA_END(list); return argCount; }
The above code will work with the GCC compiler, but not with the RVCT compiler. Compiled with the new definition of VA_LIST,
the call to DoNextArg will pass a copy of "list", and so the VA_ARG() macro will only update the local copy and the loop will
not make any progress.
The fix is simple - change DoNextArg to take a reference to the VA_LIST parameter, and the compiler now understands that
you are expecting to update the object as a side-effect.
|
|
|