3

Ubuntu 8.04(gccバージョン4.2.4)で動作するプログラムを10.04(gccバージョン4.4.3)に移植しています。私は次のコードを持っています:

#include <stdio.h>
#include <string.h>

int main(void) {
  char p[100] = "////abcd";
  char *t;

  /* Remove duplicate slashes, saving only one of them */
  while (t = strstr(p, "//"))
    strcpy(t, t + 1);

  printf("%s\n", p);

  return 0;
}

/abcd結果は、gcc4.2.4の場合となるはずです。4.4.3では、出力は/accdです。

両方のバージョンのgccを使用して正しい出力を提供するコード変更を提案していただけますか。できれば、ここで何が起こっているのかを説明してください。

前もって感謝します!

4

1 に答える 1

7

あなたは幸運でした。

strcpyドキュメントから:

strcpy()関数は、s2が指す文字列(終了ヌルバイトを含む)をs1が指す配列にコピーします。オーバーラップするオブジェクト間でコピーが行われる場合、動作は定義されていません。

あなたの場合、文字列は重複しており、プログラムは未定義の動作を呼び出します。

以前は機能していたが機能しなくなった理由strcpyとしては、GCCによって組み込みとして実装された可能性がありますmemmove(つまり、この状況では安全です)が、パフォーマンス上の理由から安全でないバージョンに変更されました。(これは純粋な推測です。)

これを修正するには、memmoveではなくstrcpy、次のようなものを使用します。

while (t = strstr(p, "//")) {
  memmove(t, t+1, strlen(t)); // strlen(t)'s bytes worth of data
                              // will cover the string bytes left
                              // and the \0 terminator
}

これはそれほど効率的ではありませんが、移植可能に機能します-memmove重複するメモリ領域を処理する必要があります。

于 2011-09-23T15:05:43.483 に答える