5

これは C++ の文字列に関するものです。私は長い間 C/C++ に触れていませんでした。実際、私がこれらの言語でプログラミングを行ったのは、約 7 年前の大学の最初の 1 年間だけでした。

C では、文字列を保持するために文字配列を作成する必要がありました (静的か動的かに関係なく)。つまり、配列に含まれる文字列のサイズを事前に十分に推測する必要があります。私は C++ で同じアプローチを適用しました。std::string クラスがあることは知っていましたが、それを使用することはできませんでした。

私の質問は、std::string クラスで配列/文字列のサイズを宣言しないため、書き込み時にバッファ オーバーフローが発生するかということです。つまり、C では、配列のサイズが 10 で、コンソールに 10 文字を超える文字を入力した場合、余分なデータが、配列に隣接する他のオブジェクトのメモリ領域に書き込まれます。cin オブジェクトを使用すると、std::string で同様のことが起こります。

std::string を使用する場合、C++ で事前に文字列のサイズを推測する必要がありますか?

良い!皆様のおかげです。このページには 1 つの正解はありません (さまざまな説明が提供されています)。最初の 5 には満足しています。

4

6 に答える 6

9

stringオブジェクトへのアクセスに使用しているメンバーによっては、はい。したがって、たとえば、reference operator[](size_type pos)whereを使用する場合はpos > size()、そうです。

于 2012-05-01T13:20:13.093 に答える
6

標準ライブラリの実装にバグがないと仮定すると、いいえ。Astd::stringは常に独自のメモリを管理します。

もちろん、提供するアクセサメソッドを覆して、次のstd::stringようなことをしない限り:

std::string str = "foo";
char *p = (char *)str.c_str();
strcpy(p, "blah");

ここでは保護がなく、未定義の動作を呼び出しています。

于 2012-05-01T13:18:08.440 に答える
3

std :: stringは通常、バッファオーバーフローから保護しますが、プログラミングエラーがバッファオーバーフローにつながる可能性がある状況もあります。C ++は通常、操作が文字列の境界外のメモリを参照するときにout_of_range例外をスローしますが、添え字演算子[](境界チェックを実行しない)はスローしません

std::stringオブジェクトをCスタイルの文字列に変換するときに別の問題が発生します。string :: c_str()を使用して変換を行うと、適切にnullで終了するCスタイルの文字列が得られます。ただし、文字列を配列に直接書き込む(配列へのポインタを返す)string :: data()を使用すると、nullで終了しないバッファが得られます。The only difference between c_str() and data() is that c_str() adds a trailing null byte.

最後に、多くの既存のC++プログラムとライブラリには独自の文字列クラスがあります。これらのライブラリを使用するには、これらの文字列タイプを使用するか、常に前後に変換する必要がある場合があります。このようなライブラリは、セキュリティに関してはさまざまな品質のものです。一般に、標準ライブラリを使用するか(可能な場合)、選択したライブラリのセマンティクスを理解するのが最善です。一般的に、ライブラリは、使用のしやすさや複雑さ、発生する可能性のあるエラーの種類、これらのエラーの発生のしやすさ、および潜在的な結果に基づいて評価する必要があります。https://buildsecurityin.us-cert.gov/bsi/articles/knowledge/coding/295-BSI.htmlを参照してください

cでは、原因は次のように説明されています。

void function (char *str) {
       char buffer[16];
       strcpy (buffer, str);
    }
    int main () {
      char *str = "I am greater than 16 bytes"; // length of str = 27 bytes
      function (str);
    }

このプログラムは、27バイトの文字列(str)が16バイトのみに割り当てられた場所(バッファ)にコピーされているため、予期しない動作を引き起こすことが保証されています。余分なバイトはバッファを通過し、FP、リターンアドレスなどに割り当てられたスペースを上書きします。これにより、プロセススタックが破損します。文字列のコピーに使用される関数はstrcpyであり、境界のチェックを完了しません。strncpyを使用すると、このスタックの破損を防ぐことができます。ただし、この古典的な例は、バッファオーバーフローによって関数のリターンアドレスが上書きされ、プログラムの実行パスが変更される可能性があることを示しています。関数のリターンアドレスは、関数が戻った直後に実行されるメモリ内の次の命令のアドレスであることを思い出してください。

ここにあなたの答えを満足させることができる良いチュートリアルがあります。

于 2012-05-01T13:19:09.140 に答える
2

C ++では、std::stringクラスは最小サイズで始まります(または開始サイズを指定できます)。そのサイズを超えると、std::stringより多くの動的メモリが割り当てられます。

于 2012-05-01T13:18:19.577 に答える
1

提供するライブラリが正しく記述されていると仮定すると、オブジェクトstd::stringに文字を追加してバッファオーバーフローを引き起こすことはできません。std::string

もちろん、ライブラリのバグは不可能ではありません。

于 2012-05-01T13:16:50.613 に答える
1

「C++ コードでバッファ オーバーフローは発生しますか?」

C プログラムが正当な C++ コードであり (ほとんどすべてが正当です)、C プログラムにバッファー オーバーフローがある限り、C++ プログラムにもバッファー オーバーフローが発生する可能性があります。

C よりリッチなので、C++ には C ではできない方法でバッファ オーバーフローが発生する可能性があると確信しています :-}

于 2012-05-02T11:58:43.160 に答える