0

私のバッファをstringstream5バイトのバッファに設定しました。呼び出したときにのみ、sputn必要以上の文字を読み取ることができます。どうしてこれなの?

#include <iostream>
#include <sstream>

int main()
{
    std::stringstream ss;
    char buf[5];

    ss.rdbuf()->pubsetbuf(buf, sizeof buf);
    ss.rdbuf()->sputn("hello world", 12);

    std::cout << ss.rdbuf(); // prints "Hello world"
}
4

3 に答える 3

5

pubsetbufまず、実装定義であることに注意してください。gcc では新しいバッファを設定しますが、たとえば MSVC では何も起こりません (setbuf何もしない基本クラスを呼び出します)。

ここで述べたように、オーバーフローsputnを呼び出します(または、他の方法で呼び出した効果を達成します):

put 領域がいっぱいになると (pptr() == epptr())、この関数は、overflow() を呼び出すか、overflow() を呼び出した効果を他の不特定の手段で達成する可能性があります。

オーバーフローのドキュメントによると:

pbase() で始まる文字の最初のサブシーケンスを出力シーケンスに保存し、出力領域へのポインターを更新することにより (必要な場合)、プット領域に少なくとも 1 文字分のスペースがあることを確認します。ch が traits::eof() でない場合 (つまり、traits::eq_int_type(c, traits::eof()) != true)、出力領域に配置されるか、出力シーケンスに直接保存されます。

この関数は、さらにデータを書き込む場所を定義するために、pptr、epptr、および pback ポインターを更新する場合があります。失敗した場合、関数は pptr() == nullptr または pptr() == epptr のいずれかを保証します。

基本的に、これが意味することは、より多くのデータに適合するようにバッファーのサイズを適切に変更できるということであり、gcc ではまさにこれが起こっています。実際のコードはここから取得します

const __size_type __opt_len = std::max(__size_type(2 * __capacity), __size_type(512));
const __size_type __len = std::min(__opt_len, __max_size);

512ご覧のとおり、文字列バッファーが到達できる最大サイズに達するまで、容量を 2 倍にするか、サイズを に設定します。

于 2013-06-27T21:31:46.463 に答える
0

C/C++ は明示的な境界チェックを行わないため、メモリのオーバーフローが発生する可能性があります (しかも簡単に実行できます)。Valgrind などのデバッガーでコードを実行すると、初期化されていないメモリを読み取っていることがわかります。

于 2013-06-27T21:04:24.837 に答える
-1

バッファはまだ 5 バイトの長さであり、許可されているよりも多くのバイトを必要としませんが、12 バイトを入れると、ソフトウェア プログラミングで多くの問題 (クラッシュ、UB、データ破損. ..)

strlenコピーする前に、バッファサイズに対して書き込む内容を確認するために使用できます。

于 2013-06-27T21:08:38.843 に答える