web-dev-qa-db-ja.com

strcat()の前に最初にstrcpy()する必要があるのはなぜですか?

このコードが実行時の問題を引き起こす理由:

char stuff[100];
strcat(stuff,"hi ");
strcat(stuff,"there");

しかし、これはそうではありませんか?

char stuff[100];
strcpy(stuff,"hi ");
strcat(stuff,"there");
23
Or Cyngiser

strcatはヌルターミネータを探し、それを文字列の終わりとして解釈し、そこに新しいテキストを追加し、プロセス内のヌルターミネータを上書きし、最後に新しいヌルターミネータを書き込みます。連結。

char stuff[100];  // 'stuff' is uninitialized

Nullターミネーターはどこにありますか? stuffは初期化されていないため、NULで始まるか、NULがどこにも含まれていない可能性があります。

C++では、これを行うことができます。

char stuff[100] = {};  // 'stuff' is initialized to all zeroes

これで、 'cat'の最初の文字がヌルターミネータであるため、strcatを実行できるようになり、正しい場所に追加されます。

Cでは、まだいくつかの方法で「もの」を初期化する必要があります。

char stuff[100]; // not initialized
stuff[0] = '\0'; // first character is now the null terminator,
                 // so 'stuff' is effectively ""
strcpy(stuff, "hi ");  // this initializes 'stuff' if it's not already.
34
Tim

最初のケースでは、stuffにゴミが含まれています。 strcatでは、宛先とソースの両方に適切なヌル終了文字列が含まれている必要があります。

strcat(stuff, "hi ");

stuffをスキャンして、終了する'\0'文字、コピーを開始する場所"hi "。それが見つからない場合、配列の最後から実行され、任意の悪いことが起こる可能性があります(つまり、動作は未定義です)。

問題を回避する1つの方法は次のとおりです。

char stuff[100];
stuff[0] = '\0';      /* ensures stuff contains a valid string */
strcat(stuff, "hi ");
strcat(stuff, "there");

または、stuffを空の文字列に初期化できます。

char stuff[100] = "";

これにより、stuffの100バイトすべてがゼロで埋められます(明確さの向上は、パフォーマンスの小さな問題に見合う価値があります)。

5
Keith Thompson

また、意図しない問題を引き起こす可能性があるため、strcpyまたはstrcatを使用しないことをお勧めします。

strncpy および strncat を使用してください。これらはバッファオーバーフローを防ぐのに役立ちます。

Strcatは、既存の文字列に文字列を追加します。文字列配列が空の場合、文字列の末尾(_'\0'_)を見つけられず、実行時エラーが発生します。

Linuxのマニュアルページによると、単純なstrcatは次のように実装されています。

_   char*
   strncat(char *dest, const char *src, size_t n)
   {
       size_t dest_len = strlen(dest);
       size_t i;

       for (i = 0 ; i < n && src[i] != '\0' ; i++)
           dest[dest_len + i] = src[i];
       dest[dest_len + i] = '\0';

       return dest;
   }
_

この実装でわかるように、destがc文字列値を修正するために初期化されない限り、strlen(dest)は正しい文字列長を返しません。 _char stuff[100];_に最初の値がゼロの配列があると幸運になるかもしれませんが、それに頼るべきではありません。

0
sung

stuffstrcpyを呼び出す前に初期化されていないためです。宣言stuffは空の文字列ではないため、初期化されていないデータです。

strcatは、文字列の末尾にデータを追加します。つまり、文字列内でヌルターミネータを見つけ、その後に文字を追加します。初期化されていない文字列は、nullターミネータを持つように保証されていないため、strcatがクラッシュする可能性があります。

以下のようにstuffを初期化する場合、strcatを実行できます。

char stuff[100] = "";
strcat(stuff,"hi ");
strcat(stuff,"there");
0
shf301