web-dev-qa-db-ja.com

変数の周りのスタック...破損していました

新しいファイルにデータを書き込む単純な関数があります。それは機能し、ファイルは書き込まれますが、MSVS Express 2013でのデバッグ中に上記のエラーが発生します。

void writeSpecToFile(const char *fname); //in header file.

char myChar [20];
sprintf(myChar, "aa%03daa%daa", i1, i2);
const char* new_char = myChar;
writeSpecToFile(myChar);

ご覧のとおり、sprintfを使用して文字列に変数を挿入するだけです(正常に動作します)。 myCharとnew_charのどちらを渡しても、破損エラーが発生します。

何が悪かったのか?

14
student1

なぜ20バイトの文字バッファを宣言したのですか?おそらく、sprintfはmyCharに収まるよりも多くの文字を配置しました。

代わりに、使用します

  1. std :: ostringstreamなどのより安全な構造体または
  2. 少なくとも、予想よりもはるかに大きいchar配列を宣言します(最善の方法ではありませんが、少なくともエラーは発生しませんでした)。

「私の配列の最大サイズを推測する」ルートに沿って進んでいる場合、最後にしたいことは、最後の文字まで、バッファをどのくらい大きくするかを数えることです。 1バイトずれていると、クラッシュする可能性があります。

14
PaulMcKenzie

32ビットのintを想定すると、%dで印刷すると、最大8文字が表示されます。

Format-stringには、6つのリテラルa- charactersも含まれています。0ターミネータを忘れないでください。

全体として:2*8+6+1 = 23 > 20 !!

他の非公開の入力制限がない限り、バッファは少なくとも23バイト大きくなければなりません。

個人的には、ラウンド32を与えます。

また、より適切に snprintf を使用し、オプションで完全な文字列が実際に収まることを確認します(収まらない場合は短縮文字列が取得されるため、大災害は発生しません)。

char myChar [32];
snprintf(myChar, sizeof myChar, "aa%03daa%daa", i1, i2);

Microsoftの実装 は不適合であり、0終了を保証しないことに注意してください。

9
Deduplicator