6

fgets(character, 2, fp)背景:ストリームではなく文字列から文字を取得することを除いて、模倣する小さなルーチンがあります。newBuff はパラメータとして渡される動的に割り当てられる文字列であり、文字は として宣言されchar character[2]ます。

ルーティーン:

character[0] = newBuff[0];

character[1] = '\0';

strcpy(newBuff, newBuff+1);

strcpy は、各文字が読み取られるときに情報の損失を再現します。

問題: Valgrind は、このアクティビティについて「ソースと宛先が strcpy(0x419b818, 0x419b819) で重複しています」と警告します。

この警告について心配する必要がありますか?

4

6 に答える 6

11

おそらく、標準では、これらのバッファーがオーバーラップしたときに何が起こるかを指定していません。そうです、valgrindこれについて不平を言うのは正しいです。

実際には、 strcpyコピーが左から右に順番に並んでおり (例: while (*dst++ = *src++);)、それは問題ではないことがわかるでしょう。しかし、それでも正しくなく、他の C ライブラリで実行すると問題が発生する可能性があります。

これを書くための標準的な正しい方法の1つは次のとおりです。

memmove(newBuff, newBuff+1, strlen(newBuff));

memmoveオーバーラップを処理するように定義されているためです。(ただし、ここでは、文字列を 2 回トラバースすることになります。1 回は長さを確認するため、もう 1 回はコピーするためです。最初に書いたものとstrlen(newBuff)等しいはずなので、ショートカットも使用しました。)strlen(newBuff+1)+1

于 2011-01-28T00:54:16.440 に答える
5

はい、また、関数のパフォーマンスが病的に悪いことも心配する必要があります (O(n^2)あるべきタスクに対してO(n))。文字を読み取るたびに、文字列の内容全体を 1 文字分戻すのは、非常に時間の無駄です。代わりに、現在の位置へのポインターを保持し、そのポインターをインクリメントする必要があります。

自分自身が必要memmoveまたは同等のもの (オーバーラップするバッファー間でのコピー) を必要とする状況は、ほとんどの場合、設計上の欠陥を示しています。多くの場合、それは実装上の欠陥ではなく、インターフェイスの欠陥です。

于 2011-01-28T00:57:16.043 に答える
4

はい -- の動作はstrcpy、ソースと宛先が重複しない場合にのみ定義されます。代わりにstrlenとの組み合わせを検討することもできます。memmove

于 2011-01-28T00:53:18.140 に答える
4

はい、心配する必要があります。C 標準では、ソース オブジェクトと宛先オブジェクトが重なっている場合のの動作strcpy未定義であると規定されています。未定義の動作とは、動作する場合もあるし、失敗する場合もある、成功したように見えてもプログラムの別の場所で失敗する場合があることを意味します。

于 2011-01-28T00:53:18.373 に答える
3

strcpy()ソースと宛先が重複する場合の の動作は公式には未定義です。

memcpy のマンページからの提案があります。

memcpy() 関数は、メモリ領域 s2 からメモリ領域 s1 に n バイトをコピーします。s1 と s2 がオーバーラップする場合、動作は未定義です。s1 と s2 がオーバーラップする可能性のあるアプリケーションでは、代わりに memmove(3) を使用する必要があります。

于 2011-01-28T00:53:15.893 に答える
2

答えはイエスです。特定のコンパイラ/ライブラリの実装、私が推測する最新のものでは、偽の結果になるでしょう。strcpy の実装方法を参照してください。たとえば。

于 2012-12-09T13:48:13.390 に答える