web-dev-qa-db-ja.com

私の場合はstrncpyまたはstrlcpy

コピーしたいときに何を使うべきですかsrc_strからdst_arr なぜ?

char dst_arr[10];
char *src_str = "hello";

PS:良いまたは悪いstrncpystrlcpy

注:strlcpyがどこでも利用できるわけではないことを私は知っています。ここではそれは問題ではありません。

18
hari

strncpy is never宛先文字列がゼロで終了している場合の正解。 strncpyは、終了していないfixed-width文字列で使用することを目的とした関数です。より正確には、その目的は、(コピーによって)ゼロで終了する文字列を終了しない固定幅の文字列に変換することです。言い換えると、strncpyはここでは意味のある適用はできません。

ここでの実際の選択は、strlcpyとプレーンstrcpyの間です。

_dst_arr_への「安全な」(つまり、切り捨てられる可能性のある)コピーを実行する場合、使用する適切な関数はstrlcpyです。

_dst_ptr_...については「_dst_ptr_にコピー」などはありません。 _dst_ptr_が指すmemoryにコピーできますが、最初に、どこかを指していることを確認し、そのメモリを割り当てる必要があります。それを行うには多くの異なる方法があります。

たとえば、_dst_ptr_を_dst_arr_を指すようにすることができます。この場合、答えは前の場合と同じです-strlcpy

または、mallocを使用してメモリを割り当てることができます。割り当てたメモリの量が文字列に対して十分であることが保証されている場合(つまり、少なくともstrlen(src_str) + 1バイトが割り当てられている場合)、プレーンなstrcpyまたはmemcpyを使用して文字列をコピーできます。この場合、strlcpyを使用する必要はなく、使用する理由もありませんが、何らかの理由で安全性が増すため、使用することを好む人もいます。

意図的に割り当てるメモリを減らした場合(つまり、文字列を切り捨てたい場合)、strlcpyが使用する適切な関数になります。

31
AnT

strlcpy()strncpy()より安全なので、使用した方がよいでしょう。
それを持たないシステムは、同じことをするs_strncpy()を持っていることがよくあります。

:何かを指すまでdst_ptrに何もコピーできません

5
Martin Beckett

私はstrlcpyを知りませんでした。私はちょうど見つけました ここ それ:

Strlcpy()関数とstrlcat()関数は、それぞれ文字列をコピーして連結します。これらは、strncpy(3)およびstrncat(3)のより安全で一貫性があり、エラーが発生しにくい置換になるように設計されています。

したがって、strlcpyの縫い目はより安全です。

編集:完全な議論が利用可能です ここ

Edit2

私が上で書いたことはあなたの質問の「あなたの場合」の部分に答えないことを私は理解します。 strncpyの制限を理解している場合は、それを使用して、落とし穴を回避するための適切なコードを記述できると思います。ただし、その制限についての理解がよくわからない場合は、strlcpyを使用してください。

Strncpyとstrlcpyの制限についての私の理解は、strncpy(バッファオーバーフロー)で非常に悪いことをすることができ、strlcpyでできる最悪のことは、その過程で1つの文字を失うことです。

2
jfg956

常に標準関数(この場合はC11 strcpy_s()関数)を使用する必要があります。 strncpy()ではありません。これは安全ではなく、ゼロ終了を保証しないためです。また、OpenBSDのみのstrlcpy()も安全ではないため、OpenBSDは常に独自の発明を考え出しますが、通常は標準にはなりません。

http://en.cppreference.com/w/c/string/byte/strcpy を参照してください

関数strcpy_sはBSD関数strlcpyに似ていますが、strlcpyがソース文字列を切り捨てて宛先に合わせる点が異なります(これはセキュリティ上のリスクです)。

  • strlcpyは、strcpy_sが実行するすべてのランタイムチェックを実行するわけではありません。
  • strlcpyは、宛先をnull文字列に設定したり、呼び出しが失敗した場合にハンドラーを呼び出したりしても、失敗を明確にしません。
  • Strcpy_sは潜在的なセキュリティリスクのために切り捨てを禁止していますが、代わりに境界チェックされたstrncpy_sを使用して文字列を切り捨てることは可能です。

Cライブラリにstrcpy_sがない場合は、safeclibを使用してください。 https://rurban.github.io/safeclib/doc/safec-3.1/df/d8e/strcpy__s_8c.html

1
rurban