2013-11-29 58 views
0
#include <cstdio> 
#include <iostream> 

using namespace std; 

int main() 
{ 
     char buffer [1];  
     sprintf (buffer, "%d is one number", 1); 
     cout<<buffer<<endl; 

     return 0; 
} 

buffer的大小隻有一個,但cout可以打印正確的結果是小。爲什麼?爲什麼它是正確的緩衝區大小下使用時的sprintf ++

安全嗎?或者在使用char *相關方法時,我不得不考慮爲緩衝區設置一個大尺寸?

+0

參考 http://stackoverflow.com/questions/3919995/determining-sprintf-buffer-size-whats-the-standard – Bunny

+0

你被允許拍攝自己的腳在C++中。你超越了'buffer'數組,但顯然這在運行時不會引起足夠嚴重的問題,導致程序運行異常。就「cout」而言,「buffer」只是一個指向空終止字符串的指針。 –

+0

這是不對的;這是未定義的行爲,只是:[undefined](http:// stackoverflow。COM /問題/ 2397984 /不確定的,非指定和實現定義的行爲/ 4105123#4105123)。 – WhozCraig

回答

0

不,它不安全。

C風格的字符串需要以null結尾,但buffer中沒有足夠的空間。未定義的行爲並不意味着保證工作或不工作。當我測試你的程序時,我遇到了分段錯誤。

0

至於俞灝說:這不安全! 但是它爲什麼有時會工作?

char buffer[1] 

不是託管數組。它只是給編譯器提示他應該爲一個char保留空間。變量緩衝區被用作指向該空間的指針並丟失關於原始大小的所有信息。所以上面的語句是一樣的文字:

char bufferVar = '\0'; /* a single character */ 
char *buffer = &bufferVar; /* a pointer to bufferVar */ 

緩衝區只包含一個字符,但沒有其他信息在所有的地址! 你的sprintf希望這樣一個地址很開心寫入從緩衝區開始的字符串。

分段錯誤是來自操作系統的消息。您的進程爲一個字節分配空間。操作系統在頁面(段)中管理你的內存。當您跨越這些分段的邊界時,會引發分段故障。 據我所知,它取決於編譯器,變量是分配在段的開始還是結尾。

餘浩的編譯器顯然把它們放在最後 - 你在前面。所以你的sprintf不會寫在一個段的邊界上。

希望它有幫助。

+0

「OS以頁面(段)的形式管理你的內存,當你跨越這些段的邊界時,會引發分段錯誤。」這部分是明顯錯誤的。 –

+0

其簡化 - 我同意!平原錯了? http://en.wikipedia.org/wiki/Segmentation_fault –

+0

根據該網頁,如果它仍然是20世紀70年代,你會是對的。分割錯誤的確最初指的是現在所謂的頁面錯誤,但今天的含義卻完全不同。 –

0

至於考慮存儲char *字符串所需的大小,許多C stdlib字符串函數會告訴你它們需要的長度,如果你通過它們NULL。您可以爲字符串分配存儲之前調用該知道你是多麼的存儲需要:

std::cout << "You need a buffer that can store " 
      << sprintf (NULL, "%d is one number", 1) + 1 
      << " characters to safely store your string." 
      << std::endl; 

另一種解決方案是使用像snprintf (...),以保證其將截斷輸出,這樣就不會溢出的緩衝區:

snprintf (buffer, 1, "%d is one number", 1); 
       // ~~~ 
       // Length of buffer 

在你的情況,緩衝區只有1個字符長,所以它只有足夠的空間來存儲空終止符;不是特別有用。

相關問題