I want to extend the regular sprintf() to take advantage unknown string lengths and my own memory manager. Hence I set out to write a little wrapper to precalculate the string length, allocate it manually and then do the sprintf() operation. This seemed like a straightforward task until it started crashing my program. As it stands, working out what is wrong has proven to be somewhat of a formidable task. Here's my initial code:
ISharedPtr<char> SPRINT(IN ISharedPtr<char>& buf, char * fmt, ...)
{
va_list ap;
int iFmtLen = 0;
if(fmt == NULL)
{ return buf = null; }
//if buf is allocated, free it
if(buf != null)
{ Delete(buf); }
va_start(ap, fmt);
//#get the length
#ifdef WIN32
//I was using the VC version of snprintf(), but it started crashing so after a bit of googling
//it turned out _scprintf() should be specialized for the task. It fails in the same way.
iFmtLen = _scprintf(fmt, ap);//_snprintf(NULL, 0, fmt, ap); // <- PROBLEM HERE
#else
iFmtLen = snprintf(NULL, 0, fmt, ap);
#endif
//use my allocator
buf = NewArray(char, iFmtLen + 1);
//do regular sprintf()
vsprintf(buf.ptr, fmt, ap);
va_end(ap);
return buf;
}
The symptoms: granted, I don't know the printX() functions in detail, but my first question arises when outputting the fmt argument after entering SPRINT(). It shows up as:
fmt before entering SPRINT(): '%d'
fmt when output to console from inside SPRINT(): '4245253'
Inspecting fmt while debugging shows the expected '%d'
Passing the format directly to _scprintf() like so:
_scprintf("'%d", 100000000);
produces the expected length of 9. Passing it as it is in the code produces 7 or some similar incorrect result. What totally screws everything up and causes the entire program to crash inside output.c (SDK file), though, is passing a string in as a variadic argument: fmt = "%s"
All arguments are correct and all variadic types match the format. What am I missing here?
PS - I would appreciate not being reminded that I should be using boost::shared_ptr or whatnot.
Edit: the title is likely pretty misleading...