the_source
the_source

Reputation: 648

Variable arguments weirdness

Ok, so this piece of code works fine in the Debug but not in Release build.

int AddString(LPCTSTR lpszString, ...)
{
    RArray<LPCTSTR> strings;
    va_list args;
    va_start(args, lpszString);
    do
    {
        strings.Add(lpszString); 
    } while (lpszString = va_arg(args, LPCTSTR));
    va_end(args);

    // ... rest of code ...
}

It seems in Release, va_arg just returns an extra value containing rubbish. So if I pass on 3 parameters: I fetch 3 in Debug and miraculously 4 in Release... How is this possible? Using VS2010 btw.

(RArray is just a simple template class comparable to MFC's CArray, does not influence results)

Thanks!

Edit: I call it like this

AddString(_T("Hello, world!"), _T("Hallo, wereld!"), _T("Hallo, Welt!"));

Upvotes: 2

Views: 195

Answers (3)

Cheers and hth. - Alf
Cheers and hth. - Alf

Reputation: 145279

va_arg does not offer any guarantee to return 0 after last real argument.

If you're going to use the C style variable arguments, then you need to establish some way of determining the number of arguments, e.g. a count or a terminating zero.

For example, printf determines the arguments from the format specification argument.

In C++ you can often, instead, use chained calls, such as the operator<< calls used for standard iostreams.

The simple, basic idea is that the operator or function returns a reference to the object that it is called on, so that further operator or function calls can be appended.

Cheers,

Upvotes: 0

Karoly Horvath
Karoly Horvath

Reputation: 96266

You're doing it the wrong way and you're just lucky with the debug build.

Notice that va_arg does not determine either whether the retrieved argument
is the last argument passed to the function (or even if it is an element
past the end of that list). The function should be designed in such a way
that the amount of parameters can be inferred in some way by the values of
either the named parameters or the additional arguments already read.

Supply either the length of the list in an integer or pass a NULL at the end of the list.

Upvotes: 2

NPE
NPE

Reputation: 500367

You're not supplying the final NULL argument your function expects. You have to do this yourself at the point where you call AddString:

AddString(_T("Hello, world!"), _T("Hallo, wereld!"), _T("Hallo, Welt!"), NULL);

It is likely that the debug build zeros out some memory that the release build doesn't. This could explain why your code works in debug but not in release.

Also, you might want to convert the do {} while (...) loop into while (...) {}, to make sure your code doesn't malfunction if no optional arguments are given.

Upvotes: 0

Related Questions