96

編集:例のソースを追加しました。

私はこの例に出くわしました:

char source[MAX] = "123456789";
char source1[MAX] = "123456789";
char destination[MAX] = "abcdefg";
char destination1[MAX] = "abcdefg";
char *return_string;
int index = 5;

/* This is how strcpy works */
printf("destination is originally = '%s'\n", destination);
return_string = strcpy(destination, source);
printf("after strcpy, dest becomes '%s'\n\n", destination);

/* This is how strncpy works */
printf( "destination1 is originally = '%s'\n", destination1 );
return_string = strncpy( destination1, source1, index );
printf( "After strncpy, destination1 becomes '%s'\n", destination1 );

この出力を生成したもの:

宛先はもともと = 'abcdefg'
strcpy の後、宛先は「123456789」になります

destination1 はもともと = 'abcdefg' です
strncpy の後、destination1 は '12345fg' になります

これは、なぜ誰もがこの効果を望んでいるのか疑問に思います. 混乱しそうです。このプログラムは、Tom Bro763 で誰かの名前 (Tom Brokaw など) を基本的にコピーできると思います。

strncpy() over を使用する利点は何strcpy()ですか?

4

10 に答える 10

194

このstrncpy()関数は、元のUNIXディレクトリエントリの方法で保存された文字列を操作するという非常に特別な問題を念頭に置いて設計されました。これらは短い固定サイズの配列(14バイト)を使用し、nul-terminatorはファイル名が配列より短い場合にのみ使用されました。

それが2つの奇妙なことの背後にあるものですstrncpy()

  • 完全にいっぱいになった場合、宛先にnul-terminatorを配置しません。と
  • 常に目的地を完全に埋め、必要に応じてnulを使用します。

「より安全」な場合は、次のようにstrcpy()使用することをお勧めします。strncat()

if (dest_size > 0)
{
    dest[0] = '\0';
    strncat(dest, source, dest_size - 1);
}

これにより、結果は常に無効になり、必要以上にコピーされることはありません。

于 2009-08-11T05:29:57.350 に答える
101

strncpyバッファオーバーフローに長さを設定するように要求することで、バッファオーバーフローと戦います。strcpy末尾に依存しますが、\0常に発生するとは限りません。

次に、7文字の文字列に5文字だけをコピーすることを選択した理由は私にはわかりませんが、期待どおりの動作が得られます。n最初の文字をコピーするだけです。ここnで、は3番目の引数です。

これらのn関数はすべて、バッファオーバーフローに対する防御コーディングとして使用されます。などの古い関数の代わりに使用してくださいstrcpy

于 2009-08-11T05:21:29.473 に答える
36

私はその背後にある意図を知ってstrncpyいますが、それは本当に良い機能ではありません。両方を避けてください。レイモンドチェンは説明します

strncpy個人的に、私の結論は、nullで終了する文字列を扱っている場合は、そのすべての友人を避けることです。名前に「str」が含まれているにもかかわらず、これらの関数はnullで終了する文字列を生成しません。これらは、nullで終了する文字列を生の文字バッファに変換します。2番目のバッファが明らかに間違っているため、nullで終了する文字列が予想される場合にそれらを使用します。ソースが長すぎると適切なnull終了が得られないだけでなく、ソースが短すぎると不要なnullパディングが発生します。

strncpyが安全でない理由も参照してください。

于 2009-08-11T05:29:49.207 に答える
27

strncpy は strcpy よりも安全ではありません。あるタイプのバグを別のタイプのバグと交換するだけです。C では、C 文字列を処理するときに、バッファーのサイズを知る必要があります。それを回避する方法はありません。strncpy は、他の人が言及したディレクトリのことで正当化されましたが、それ以外の場合は決して使用しないでください:

  • 文字列とバッファの長さがわかっている場合、なぜ strncpy を使用するのですか? せいぜい計算能力の無駄です(無駄な0を追加します)
  • 長さがわからないと、文字列を静かに切り詰める危険があります。これは、バッファ オーバーフローよりもはるかに優れています。
于 2009-08-11T06:27:20.650 に答える
23

あなたが探しているのは、strlcpy()常に文字列を 0 で終了し、バッファを初期化する関数です。また、オーバーフローを検出することもできます。唯一の問題は、(実際には) 移植性がなく、一部のシステム (BSD、Solaris) にのみ存在することです。この関数の問題は、 http://en.wikipedia.org/wiki/Strlcpyでの議論からわかるように、ワームの別の缶を開けることです 。

strncpy()私の個人的な意見では、やよりもはるかに便利ですstrcpy()。より優れたパフォーマンスを発揮し、 との優れたコンパニオンsnprintf()です。それを持たないプラットフォームの場合、実装は比較的簡単です。(アプリケーションの開発段階では、これら 2 つの関数 (snprintf()strlcpy()) を、バッファ オーバーフローまたは切り捨てが発生した場合にプログラムを容赦なく中止するトラップ バージョンに置き換えます。これにより、最悪の違反者をすばやく見つけることができます。特に、他の誰かからのコードベースで作業している場合.

編集:strlcpy()簡単に実装できます:

size_t strlcpy(char *dst, const char *src, size_t dstsize)
{
  size_t len = strlen(src);
  if(dstsize) {
    size_t bl = (len < dstsize-1 ? len : dstsize-1);
    ((char*)memcpy(dst, src, bl))[bl] = 0;
  }
  return len;
}
于 2009-08-11T07:59:11.480 に答える
3

このstrncpy()関数はより安全です。宛先バッファーが受け入れることができる最大長を渡す必要があります。そうしないと、ソース文字列が正しく0で終了しない可能性があります。その場合、strcpy()関数は宛先にさらに文字を書き込み、宛先バッファの後にメモリ内にあるものをすべて破壊する可能性があります。これは、多くのエクスプロイトで使用されるバッファオーバーランの問題です。

read()また、終端の0をバッファーに入れずに、読み取ったバイト数を返すようなPOSIX API関数の場合は、手動で0を入れるか、を使用してコピーしstrncpy()ます。

サンプルコードでは、indexは実際にはインデックスではありませんが、 -ソースから宛先にコピーする最大count文字数を示します。ソースの最初のnバイトの中にヌルバイトがない場合、宛先に配置された文字列はヌル終了されません

于 2009-08-11T05:23:08.393 に答える
1

strncpy は、送信先のサイズが小さいにもかかわらず、送信元のサイズに対して '\0' で送信先を埋めます....

マンページ:

src の長さが n 未満の場合、strncpy() は dest の残りの部分を NULL バイトで埋めます。

残りだけでなく...この後もn文字に達するまで。したがって、オーバーフローが発生します... (マニュアルページの実装を参照)

于 2013-11-01T16:42:53.453 に答える
-1

これは、元の文字列の一部のみを宛先にコピーする必要がある他の多くのシナリオで使用できます。strncpy()を使用すると、strcpy()とは対照的に、元の文字列の限られた部分をコピーできます。あなたが作成したコードはpublib.boulder.ibm.comからのものだと思います。

于 2009-08-11T05:29:15.650 に答える
-1

それは私たちの要件によって異なります。Windows ユーザーの場合

文字列全体をコピーしたくない場合、または n 個の文字のみをコピーしたい場合はいつでも strncpy を使用します。ただし、strcpy は、終端の null 文字を含む文字列全体をコピーします。

これらのリンクは、strcpy と strncpy および使用できる場所について詳しく知るのに役立ちます。

strcpyについて

strncpyについて

于 2016-05-24T11:12:52.787 に答える
-8

strncpyはstrcpyのより安全なバージョンです。実際のところ、strcpyを使用しないでください。これは、システムがあらゆる種類の攻撃に対して脆弱になる可能性があるバッファオーバーフローの脆弱性があるためです。

于 2009-08-11T05:21:33.390 に答える