Symbian
Symbian OS Library

FAQ-1207 Why might code using VA_LIST stop working when I use the RVCT compiler?

[Index][spacer] [Previous] [Next]



 

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.