簡體   English   中英

如果存儲字符串的char數組小於字符串,C ++真的存儲字符串?

[英]Where C++ really stores a string if the char array that stores it is smaller than a string is?

我正在從“C ++ Premiere”一書中測試一個關於C ++中字符串的例子。

const int size = 9;
char name1[size];
char name2[size] = "C++owboy";   // 8 characters here

cout << "Howdy! I'm " << name2 << "! What's your name?" << endl;

cin >> name1;  // I input "Qwertyuiop" - 11 chars. It is more than the size of name1 array;

// now I do cout
cout << "Well, your name has " << strlen(name1) << " letters";  // "Your name has 11 letters".
cout << " and is stored in an array of " << size(name1) << " bytes"; // ...stored in an array of 9 bytes.

怎樣才能將11個字符存儲在一個數組中,僅用於8個字符+'\\ 0'char? 它在編譯時變寬了嗎? 或者字符串存儲在其他地方?

另外,我做不到:

const int size = 9;
char name2[size] = "C++owboy_12345";   // assign 14 characters to 9 chars array

但是可以做我上面寫的:

cin >> name1;   // any length string into an array of smaller size

這里的訣竅是什么? 我使用NetBeans和Cygwin g ++編譯器。

將更多條目寫入數組而不是數組大小允許調用未定義的行為 計算機可能會將數據存儲在任何位置,或者根本不存儲它。

通常,數據存儲在內存中接下來發生的任何事情中。 這可能是另一個變量,指令流,甚至是椅子下方炸彈的控制寄存器。

簡單地說:你已編寫了一個緩沖區溢出錯誤。 不要那樣做。


只是為了好玩未定義的行為是C ++標准不評論的行為。 它可以是任何東西,因為標准沒有限制它。

在一個特殊情況下,這種行為使我的銀行余額從10美元增加到18億美元: http//ideone.com/35FQW

你能明白為什么那個程序可能會這樣嗎?

name1在內存中被賦予一個地址。 如果你寫80個字節,它將從該位置開始在內存中寫入超過80個字節。 如果存在一個存儲在name1的地址+20的變量,那么它將通過向name1寫入80個字節來覆蓋其數據。 這就是C / C ++中的工作方式,這些被稱為緩沖區溢出,可用於破解程序。

這里沒有技巧:)你在緩沖區之外的內存寫,這是一個未定義的bahaviour

這是典型的緩沖區溢出。 這就是為什么你總是應該檢查輸入的大小,如果你把它放在緩沖區。 這是發生了什么:

在C ++(和C)中,數組名稱只是指向數組第一個元素的指針。 編譯器知道數組的大小,並將進行一些編譯時檢查。 但是,在運行時,它只會將其視為char *。

當您執行cin >> name1 ,您將char *傳遞給cin cin不知道分配的空間有多大 - 它只是一個指向某個內存的指針。 因此,它假設您分配了足夠的空間,寫入所有內容,並超過了數組的末尾。 這是一張圖片:

Bytes   1  2  3  4  5  6  7  8  9  10 11 12 13 14 15
Before  |-----name1 array-------|  |--- other data-|
After   Q  w  e  r  t  y  u  i  o  p  \0 |-er data-|

如您所見,您已覆蓋在陣列之后存儲的其他數據。 有時這個其他數據只是垃圾,但有時它很重要,可能意味着一個棘手的錯誤。 更不用說,這是一個安全漏洞,因為攻擊者可以用用戶輸入覆蓋程序內存。

關於大小的混淆是因為strlen會計算字節,直到找到'\\0' (空終止符),這意味着它找到10個字符。 另一方面, size(name1)使用編譯器提供的數組的實際大小。

由於這些問題,每當您看到一個以數組作為參數的C函數時,它也會占用數組大小​​。 否則無法分辨出它有多大。 為了避免這些問題,使用像std :: string這樣的C ++對象要好得多。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM