12

コード:

int str_join(char *a,  const char *b) {
   int sz =0; 
   while(*a++) sz++;  
   char *st = a -1, c;  
   *st = (char) 32;
   while((c = *b++)) *++st = c;  
   *++st = 0;
   return sz;
}

....

char a[] = "StringA"; 
printf("string-1 length = %d, String a = %s\n", str_join(&a[0],"StringB"), a);

出力:

string-1 長さ = 7、文字 *a = StringA StringB

*** スタック破壊が検出されました **** : /T02 が終了しました

中止 (コアダンプ)

スタックスマッシングが表示される理由がわかりません。*スタックスマッシングとは何ですか?それとも私のコンパイラのエラーですか?

4

2 に答える 2

12

スタック破壊またはスタック バッファ オーバーフローは、ここで説明するかなり詳細なトピックです。詳細については、この wiki 記事を参照してください。

ここに示されているコードに来ると、問題は、配列aが最終的な連結結果を保持するのに十分な大きさではないことです。

それによって、言うことによって

 while((c = *b++)) *++st = c;

基本的に、未定義の動作を引き起こす境界外のメモリにアクセスしています。これが、プロセスに属していないメモリにアクセスしようとしているため、「スタック破壊」の問題が発生する理由です。

これを解決するには、連結された最初の文字列aと 2 番目の文字列の両方を保持するのに十分なスペースが配列に含まれていることを確認する必要があります。つまり、より大きな宛先配列を提供する必要があります。

于 2016-11-04T06:27:50.240 に答える
6

スタックスマッシングとは、ローカル変数用の関数のストレージ領域の外側 (過去/を通じて「スマッシュ」) を記述したことを意味します (この領域は、ほとんどのシステムおよびプログラミング言語で「スタック」と呼ばれます)。「スタック オーバーフロー」や「スタック アンダーフロー」と呼ばれるこのタイプのエラーが見つかる場合もあります。

あなたのコードでは、C はおそらく が指す文字列をaスタックに置いています。あなたの場合、スタックスマッシュが発生する場所は、元のポインターstを超えてインクリメントし、それが指す場所に書き込むときです。aa

Cですでに適切に「予約」されているメモリ領域の外に書き込むときはいつでも、それは「未定義の動作」です(これは、C言語/標準が何が起こるかを述べていないことを意味します):通常、プログラムのメモリ (通常、プログラムは、リターン アドレスやその他の内部詳細など、他の情報をスタック上の変数のすぐ隣に置きます)、またはプログラムが、オペレーティング システムが使用を "許可" しているメモリの外側に書き込もうとします。いずれにせよ、プログラムは通常、すぐに明らかに (たとえば、「セグメンテーション違反」エラーで) 壊れます。

この場合、コンパイラはこの問題を検出するための特別な保護を備えたプログラムを構築しているため、プログラムはエラー メッセージを表示して終了します。コンパイラがそれを行わなかった場合、プログラムは実行を継続しようとしますが、最終的に間違ったことをしたり、クラッシュしたりする可能性があります。

解決策は、結合された文字列に十分なメモリがあることをコードに明示的に伝える必要があるということです。「a」配列の長さを両方の文字列に十分な長さに明示的に指定することでこれを行うことができますが、それは通常、必要なスペースが事前にわかっている単純な用途にのみ十分です。汎用ソリューションの場合malloc、完全なサイズがどうなるかを計算したら、必要な/必要なサイズを持つオペレーティングシステムからメモリの新しいチャンクへのポインターを取得するような関数を使用します (使い終わっfreeたら、取得したポインターや同様の関数を呼び出すことを忘れmallocないでください)。

于 2016-11-04T06:43:06.880 に答える