Advertisement

cstdarg in g++

Started by January 30, 2004 05:31 PM
4 comments, last by cozman 20 years, 9 months ago
I''m having a little bit of trouble using the cstdarg functions in g++, this code worked fine in VC++7, and I believe in older version s of g++. I have a function like:

std::string FormatStr(std::string fmtStr, ...)
{
    std::va_list args;
    char buf[1024];

    va_start(args,fmtStr);
    std::vsprintf(buf,fmtStr.c_str(),args);
    va_end(args);

    return buf;
}
 
But I''m getting a warning In function `std::string FormatStr(std::basic_string, std::allocator >, ...)'': warning: cannot pass objects of non-POD type `struct std::string'' through `...'' The warning seems to point me to the line va_start(args,fmtStr).. I''m a little bit confused about this, as I thought va_start was basically (and probably oversimplified) a macro which found the first parameter on the stack after the given argument. It''s not any problem for me to change the fmtStr parameter to a char*, and in my code I''ve currently done that, I''m more asking this question because I was wondering if anyone knows what the error really means, and why it doesn''t work as expected in g++. PS. running the code often yields random results, for example a format string like "I am %d years old, I have %f dollars, and my middle name is %s" and the values 30,100.0, and "Lloyd" entered in yields: I am 30 years old, I have 0.00 dollars, and my middle name is (garbage).
Modify your function like this and the problem should be obvious:
std::string FormatStr( std::string fmtStr, ... ){    std::va_list args;    char buf[1024];    std::cout << fmtStr.length() << std::endl;    va_start( args, fmtStr );    std::vsprintf( buf, fmtStr.c_str(), args );    va_end( args );    std::cout << fmtStr.length() << std::endl;    return buf;}

The call to vsprintf does not automatically resize the string. You're writing past the end of the string which causes bad things to happen.

As for the error message, POD is "plain old data". That means you can't use things like structs or classes with variable argument lists.

Changing fmtStr to a char*, like you've already done, is the best solution. You might also want to consider if cstdarg is the best way to handle this. Maybe a stringstream would be better?

Tony


[edited by - AnthonyLewis on January 30, 2004 11:06:03 PM]
Advertisement
quote: Original post by AnthonyLewis
As for the error message, POD is "plain old data". That means you can't use things like structs or classes with variable argument lists.


Stricto-sensu, you can pass a struct that only uses C features - it's a POD.

“Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.” — Brian W. Kernighan (C programming language co-inventor)

[edited by - Fruny on January 30, 2004 11:15:05 PM]
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
@Anthony: I think you are mistaken. The destination is "buf". "buf" is a plain array. (although I suggest using vsnprintf if possible, to avoid buffer overruns).

@cozman: I think the problem is that the macro used to implement va_start() does not work with C++ class instances in the library version you''re using. Sucks to be you. Try changing the function to take a char const * and pass string::c_str() into the function instead.
enum Bool { True, False, FileNotFound };
That clears it up quite a bit, I am reconsidering my use of cstdarg, I was just curious as to what that particular error was, I see the problem now. Thanks for clearing it up, that explanation makes a lot of sense.
quote: Original post by hplus0603
@cozman: I think the problem is that the macro used to implement va_start() does not work with C++ class instances in the library version you''re using. Sucks to be you.


It''s not a problem specific to his library. The C++ standard explicitely state that passing non-POD types to a variadic function has undefined behaviour (meaning "don''t do this"). Were you to try it, you wouldn''t fare any better.

“Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.” — Brian W. Kernighan (C programming language co-inventor)
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan

This topic is closed to new replies.

Advertisement