组合std::strings和C-strings会导致缓冲区溢出 我尝试在C++的WiLAPI应用程序中,使C字符串和 STD::StryS合并的功能更容易。

组合std::strings和C-strings会导致缓冲区溢出 我尝试在C++的WiLAPI应用程序中,使C字符串和 STD::StryS合并的功能更容易。,c++,winapi,cstring,C++,Winapi,Cstring,因此,与其这样做,不如: 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 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数组):

我的问题:我的函数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);
}
<> >在微软Visual C++中运行函数时发生的错误是:

Application.exe中发生缓冲区溢出,该缓冲区已 已损坏程序的内部状态。按“中断”以调试 或继续终止程序

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


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

要纠正第一个错误,您需要使用接受printf的varargs版本。对于第二种情况,在打印前应先计数:

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]);
}
tstring WinFile::concat(TCHAR const*strFormat,…)
{
va_列表参数;
//确定要保留多少空间。
va_启动(参数、标准格式);
大小消息长度=\u vsctprintf(标准格式,参数);
va_端(args);
//在堆上保留空间。
//
//“_vscprintf返回将生成的字符数
//如果打印了参数列表指向的字符串。。。
//[和]不包括终止的空字符。“
//
//因此,我们为一个终止null添加了空间。
标准:向量写入缓冲区(1+msg_len);
//执行格式化
va_启动(参数、标准格式);
_vstprintf(&writebuffer[0],strFormat,args);
va_端(args);
//将副本作为tstring返回。
返回tstring(&writebuffer[0],&writebuffer[msg_len]);
}

为什么要声明res具有MAX\u路径字符?您没有复制到它的路径。猜测一下,我想说您正在尝试向res写入超过MAX_PATH的字符。作为一个选项,您可以使用ATL::CString。它有格式方法。大写字母
STD
有什么特殊原因吗?这通常意味着性传播疾病,不是吗?C++标准库命名空间是代码> STD<代码>,在小写中,我认为 CONTACA//COD>作为一个名字有点误导。也许
WinFile::format\u msg
?谢谢您的指导。我在声明writebuffer时出错:“表达式必须有一个常量值”。是唯一的声明向量或使用TStand的方法吗?动态大小的数组不是标准C++吗?那么最好只使用
std::vector
。特别是,试图用c风格的函数(
\u vstprintf
)直接写入
tstring
)几乎肯定是个坏主意。我相应地修改了我的答案。
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]);
}