954,498 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

UNIX: _vscprintf not compiling

I am trying to write a variable argument function on SUN solaris. According to MSDN, the _vscprintf function that I'm using on windows should work on unix as ANSI is listed.
_vscprintfANSI, Win 98, Win Me, Win NT, Win 2000, Win XP
However, including stdio.h doesn't seem to help. Is this function located in some other header file on unix?

winbatch
Posting Pro in Training
466 posts since Feb 2005
Reputation Points: 68
Solved Threads: 18
 

>should work on unix as ANSI is listed.
_vscprintf isn't a standard C function. It's a Microsoft extension that is unlikely to work on Unix.

Narue
Bad Cop
Administrator
15,460 posts since Sep 2004
Reputation Points: 6,464
Solved Threads: 1,401
 

So their indication of ANSI means nothing? ########.

Any alternative way to find out the length of the string so that I can properly allocate memory?

This is the current function (errorMessage is a class member string)

DHException (const char * exceptText, ...)
 
{
 
 
 
va_list args;
 
int len;
 
char * buffer;
 
va_start( args, exceptText );
 
len = _vscprintf( exceptText, args )+ 1; // terminating '\0'
 
buffer = new char[ len * sizeof(char)];
 
vsprintf( buffer, exceptText, args );
 
errorMessage = buffer;
 
delete [] buffer;
 
}
winbatch
Posting Pro in Training
466 posts since Feb 2005
Reputation Points: 68
Solved Threads: 18
 

>So their indication of ANSI means nothing?
They're probably talking about naming conventions, not strict standard conformance.

>Any alternative way to find out the length of the string so that I can properly allocate memory?
Not easily. You would have to resize the buffer as you go. But since this is C++, why not just use a std::string? :)

>buffer = new char[ len * sizeof(char)];
sizeof(char) is guaranteed to be 1, so you can safely say:

buffer = new char[len];

>errorMessage = buffer;
That looks suspicious. If errorMessage is a pointer to char, you'll have problems when the memory for buffer is released.

>}
Don't forget to use va_end.

Narue
Bad Cop
Administrator
15,460 posts since Sep 2004
Reputation Points: 6,464
Solved Threads: 1,401
 

errorMessage is of type 'string'.

How do I use std::string for this? I didn't think there was a function to handle the va_arg using string.

Also, wouldn't it need to be :
buffer = new char[len +1];
to handle the null terminator?
I have added va_end( args); per your suggestion

winbatch
Posting Pro in Training
466 posts since Feb 2005
Reputation Points: 68
Solved Threads: 18
 

> I didn't think there was a function to handle the va_arg using string.
Nevermind, you probably don't want to do it that way, and it was silly of me to suggest it. Let's try this again:

>Any alternative way to find out the length of the string so that I can properly allocate memory?
A safe alternative is to use vfprintf to write to a temporary file, and use its return value the same way you're using _vscprintf:

len = vfprintf( tmpfile(), exceptText, args ) + 1;

Of course, since tmpfile can return NULL, you shouldn't use it as a direct argument like that. vfprintf and tmpfile are standard functions, so they will always be available. If you have performance issues then there are less convenient methods.

>Also, wouldn't it need to be :
>buffer = new char[len +1];
No, you did that when initializing len.

Narue
Bad Cop
Administrator
15,460 posts since Sep 2004
Reputation Points: 6,464
Solved Threads: 1,401
 

(Yes, my bad on the +1)

In your opinion, would it better to use the tmpfile(), or to establish a pre-defined maximum log length and therefore have theoretically enough buffer available to handle the log?


(Do I need to do an fclose on tmpfile() ?)

winbatch
Posting Pro in Training
466 posts since Feb 2005
Reputation Points: 68
Solved Threads: 18
 

>or to establish a pre-defined maximum log length and therefore have theoretically enough buffer
That doesn't sound safe if you still use a variadic function. You can add error handling, but then you could end up truncating error messages. I would say (without further knowledge of your application) that tmpfile is the best solution without forcing you to do a lot of extra work.

>(Do I need to do an fclose on tmpfile() ?)
You don't need to as it will be closed automagically when the program terminates. However, it's never a bad idea for functions to clean up after themselves, and if the function is called often then you could hit the limit of allowable open file streams. So it would be a good idea.

Narue
Bad Cop
Administrator
15,460 posts since Sep 2004
Reputation Points: 6,464
Solved Threads: 1,401
 

My 2 cents: In Builder6 the function vsnprintf (or vsnwprintf) do report the needed length when the input buffer size is set to zero.

noormanman
Newbie Poster
1 post since Aug 2010
Reputation Points: 10
Solved Threads: 0
 

This article has been dead for over three months

Post: Markdown Syntax: Formatting Help
You