0

我正在尝试创建一个函数,使std::string在我的 C++ WinAPI 应用程序中组合 C 字符串和 sa 更容易一些。

所以不要这样做:

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);

我只需要这样做(这使得合并不同的字符串类型变得更容易,因为我不必在任何地方都声明 TCHAR 数组):

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);

我的问题:我的函数concat(); 当我在参数格式中传递超过 1 个变量时失败,我不知道为什么?

// 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);
}

在 Microsoft Visual C++ 中运行该函数时发生的错误是:

Application.exe 中发生缓冲区溢出,已损坏程序的内部状态。按 Break 调试程序或按 Continue 终止程序。

有关详细信息,请参阅帮助主题“如何调试缓冲区溢出问题”。

4

1 回答 1

1

看起来你的可变参数处理有点不对劲。是的,通过写入固定大小的缓冲区,您要求堆栈溢出。

要更正第一个问题,您需要使用接受可变参数的 printf 版本。对于第二个,您应该在打印之前计算:

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]);
}
于 2012-05-13T05:29:32.417 回答