2017-07-03 82 views
1

使用CString.Format(),我傳遞一個std::map給予int時返回std::string爲什麼將std :: string傳遞給CString.Format()只會有時會崩潰?

所以:

CString cStr; 
cStr.Format("%s", IntToStdStringMap[1]); 

其中IntToStdStringMap[1]返回一些字符串,我們會說 「你好,世界!」。問題是這似乎並不是每次都會崩潰。最終,我會收到訪問違規。

爲什麼會這樣呢?

請記住,這改變了代碼如下:

CString cStr; 
cStr.Format("%s", IntToStdStringMap[1].c_str()); 

緩解這一問題。

任何想法?

+2

小串的優化,大概。但它仍然是未定義的行爲,所以不值得推理。 –

+2

爲CString的該文檔格式::甚至談不上傳遞對象的格式參數:https://msdn.microsoft.com/en-us/library/aa314327(v=vs.60).aspx –

+0

@MillieSmith我同意。將std :: string傳遞給CString :: Format的機會是一個意外事件,顯示了未定義的行爲。我只是想了解更多關於爲什麼在編譯時沒有錯誤。我相信尼爾正在做一件事。 –

回答

5

傳遞一個std::stringCString::Format是不對的。從https://msdn.microsoft.com/en-us/library/aa314327(v=vs.60).aspx

該格式與printf函數的格式參數具有相同的形式和功能。

這意味着,當格式說明是%s,預期參數類型是char const*,不std::string

因此,使用的

cStr.Format("%s", IntToStdStringMap[1]); 

是同時的

cStr.Format("%s", IntToStdStringMap[1].c_str()); 

行爲被很好地定義原因未定義的行爲。

+1

正確。我同意他們可能是一些小的字符串優化發生,並沒有在編譯時造成問題。無論哪種方式,我很滿意將它標記爲未定義的行爲並繼續前進。感謝您的回答! –

+0

@FrankPalmasani,當函數是'printf'時,一些編譯器能夠檢測到參數類型與格式說明符不匹配。我不確定他們是否能夠在編譯時檢測到該函數爲「CString :: Format」時的問題。誰知道編譯器生成的代碼。無論如何,我們無法試圖理解未定義的行爲。 –

+1

一些編譯器確實支持printf樣式參數的編譯時驗證,但它們通常是1)僅對'printf'及其相關函數進行硬編碼,或2)公開一個必須手動應用的特殊編譯器指令以標記類似printf的功能。例如,[Visual Studio 2015是硬編碼的](https://blogs.msdn.microsoft.com/vcblog/2015/06/22/format-specifiers-checking/),而[GCC具有'format'功能屬性(https://gcc.gnu.org/onlinedocs/gcc-3.3.2/gcc/Function-Attributes.html)。 –