Reputation: 25928
I am attempting to make a function that will make combining C Strings and std::string
s a little easier in my C++ WinAPI Application.
So instead of doing this:
TCHAR res[MAX_PATH];
_stprintf(res, _T("In functionX(): error occured where the variable values are %d, %u, %s, %c"), myInt, myUnsignedInt, myStr.c_str(), myChar);
MessageBox(NULL, res, _T("Error Occurred"), MB_OK);
I just have to do this(which makes it a little easier to merge different string types because I don't have to keep declaring TCHAR arrays everywhere):
tstring res = concat(_T("In functionX(): error occured with the variable values %d, %u, %s, %c"), myInt, myUnsignedInt, myStr.c_str(), myChar);
MessageBox(NULL, (LPTSTR)res.c_str(), _T("Error Occurred"), MB_OK);
My Problem: My function concat(); fails when I pass more than 1 variable inside the parameter format and I dont know why?
// The following function call causes the error
tstring ou = concat(_T("In functionX(): Failed to create temp file - %s - %s\r\n"), (LPTSTR)tempFileRootDir.c_str(), tempFile);
tstring WinFile::concat( TCHAR* strFormat, TCHAR* format, ... )
{
// tstring is either a std::string or std::wstring depending on whether unicode is used
// Post: Wrapper function to easily merge C++ strings with C Strings
va_list arguments;
va_start(arguments, format);
TCHAR res[MAX_PATH];
_stprintf(res, strFormat, format);
return tstring(res);
}
The error that occurs when I run the function in Microsoft Visual C++ is:
A buffer overrun has occurred in Application.exe which has corrupted the program's internal state. Press Break to debug the program or Continue to terminate the program.
For more details please see Help topic 'How to debug Buffer Overrun Issues'.
Upvotes: 0
Views: 576
Reputation: 9039
It looks like your varargs handling is a bit off. And yes, by writing to a fixed size buffer, you're asking for a stack overflow.
To correct the first, you'll need to use a varargs-accepting version of printf. For the second, you should count before you print:
tstring WinFile::concat( TCHAR const * strFormat, ... )
{
va_list args;
// Determine how much space to reserve.
va_start(args, strFormat);
size_t msg_len=_vsctprintf(strFormat, args);
va_end(args);
// Reserve space on heap.
//
// "_vscprintf returns the number of characters that would be generated
// if the string pointed to by the list of arguments was printed ...
// [and] does not include the terminating null character."
//
// So we add space for a terminating null.
std::vector<TCHAR> writebuffer(1+msg_len);
// perform formatting
va_start(args, strFormat);
_vstprintf(&writebuffer[0], strFormat, args);
va_end(args);
// return a copy as a tstring.
return tstring(&writebuffer[0], &writebuffer[msg_len]);
}
Upvotes: 1