2012-05-13 32 views
0

我試圖做一個函數,使C++ WinAPI應用程序中組合C字符串和std::string更容易一些。的結合std :: strings和C-Strings導致緩衝區溢出

所以不是這樣:

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

我的問題: My功能的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具有 損壞了程序的內部狀態。按Break鍵調試 程序或繼續終止程序。

有關更多詳細信息,請參閱幫助主題'如何調試緩衝區溢出 問題'。

+1

爲什麼要聲明res具有MAX_PATH字符?你並沒有複製到它的路徑。據猜測,我會說你想寫超過MAX_PATH字符來解析。 –

+0

作爲一個選項,你可以使用ATL :: CString。它有Format方法。 –

+1

上傳'STD'的任何特殊原因?這通常意味着性傳播疾病,不是嗎? C++標準庫名稱空間是'std',小寫。 – jalf

回答

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]); 
} 
+1

我認爲'concat'作爲一個名字有點誤導。也許'WinFile :: format_msg'? – Managu

+0

感謝您的教學。我得到一個聲明writebuffer的錯誤:「表達式必須有一個常量值」。我唯一的解決方案是聲明一個向量還是使用tstring? –

+0

動態大小的數組不是標準C++嗎?可能最好只是使用'std :: vector'。特別是,嘗試直接寫入帶有c風格函數的'tstring'('_vstprintf')幾乎肯定是一個壞主意。我相應地修改了我的答案。 – Managu