web-dev-qa-db-ja.com

strdupが悪であると考えられる理由

strdupは悪だと言っているポスターを見たことがあります。これについてコンセンサスはありますか?私は何の罪悪感もなく使用しましたが、malloc/memcpyを使用するよりも悪い理由はありません。

strdupの評判は、呼び出し元が誤用する可能性がある(たとえば、返されたメモリを解放する必要があることに気付かない、strdupされた文字列の最後までstrcatを試行する)と私が思う唯一のことです。しかし、mallocされた文字列には、誤用の可能性もありません。


質問が役に立たないと見なした人への返信と謝罪に感謝します(投票への投票)。返答を要約すると、strdup自体は悪であるという一般的な感覚はないようですが、Cの他の多くの部分と同様に、不適切または危険に使用できるという一般的なコンセンサスがあります。

「正しい」答えは実際にはありませんが、それを受け入れるために、私は@nneoneoの答えを受け入れました。

26
William Morris

私が考えることができる2つの理由:

  1. 厳密にはANSI Cではなく、POSIXです。その結果、一部のコンパイラ(MSVCなど)は使用を推奨しません(MSVCは__strdup_を優先します)。技術的にstrdupは予約済みのプレフィックスであるため、C標準は独自のstrを異なるセマンティクスで定義できます。そのため、その使用にはいくつかの潜在的な移植性の懸念があります。
  2. メモリの割り当てを隠します。他のほとんどのstr関数はメモリを割り当てないため、返された文字列を解放する必要がないとユーザーが誤解している可能性があります。

しかし、これらの点は別として、コードの重複を減らし、一般的なイディオム(strdup("constant string")など)の素敵な実装を提供して、可変で返却可能なコピーを取得できるので、strdupの慎重な使用は正当化されると思いますリテラル文字列)。

31
nneonneo

私の答えはむしろstrdupをサポートしており、Cの他の関数よりも悪くはありません。

  1. POSIXは標準であり、移植性が問題になる場合、strdupの実装はそれほど難しくありません。

  2. strdupによって割り当てられたメモリを解放するかどうかは、manページを読んでstrdupがどのように機能するかを理解するのに少し時間を費やした場合には問題になりません。関数がどのように機能するかを理解していない場合、人が何かを台無しにしようとしている可能性が高く、これはstrdupだけでなくany関数にも当てはまります。

  3. Cでは、メモリと他のほとんどのものはプログラマーによって管理されるので、strdupはfreemallocedされたメモリを忘れてnull terminateに失敗するよりも悪いことではありません=文字列、scanfで不正なフォーマット文字列を使用(および未定義の動作を呼び出す)、アクセスダングリングポインタなど.

(私は本当にこれをコメントとして投稿したかったのですが、1つのコメントを追加できませんでした。そのため、回答として投稿しました)。

19
P.P.

strdupが悪だと説明されているのは聞いたことがありませんが、一部の人々がそれを嫌ういくつかの考えられる理由:

  1. 標準Cではありません(ただし、POSIXに含まれています)。ただし、この理由は馬鹿げていると思います。なぜなら、それが欠けているシステムに追加するのは、ほぼ1行の関数だからです。
  2. 文字列を可能な限りインプレースで使用するのではなく、あちこちで盲目的に文字列を複製すると、時間とメモリが浪費され、コードに失敗のケースが導入されます。
  3. 文字列のコピーが必要な場合、実際にはそれを変更または構築するためにより多くのスペースが必要になる可能性が高く、strdupはそれを提供しません。
10
R..

Strdupに関する懸念の大部分は、バッファオーバーランに関するセキュリティの懸念、および不適切にフォーマットされた文字列に起因していると思います。 null以外で終了する文字列がstrdupに渡されると、未定義の長さの文字列を割り当てることができます。これが攻撃に具体的に利用できるかどうかはわかりませんが、一般的には、ヌル文字だけに依存するのではなく、最大長を取る文字列関数のみを使用するのが安全なコーディング方法です。

5
john-charles

多くの人は明らかにそうしませんが、私はいくつかの理由でstrdupを個人的に悪と感じています、

  • 主なものはそれが割り当てを隠すことです。その他str*関数と他のほとんどの標準関数は、後でfreeを必要としないため、strdupは無害に見え、その後のクリーンアップを忘れることがあります。 dmckeeは、後でクリーンアップする必要がある関数のメンタルリストに追加することを提案しましたが、なぜですか? 2本の中くらいの長さの行を1本の短い行に減らすことに比べて大きな利点はないと思います。

  • それは常にヒープにメモリを割り当て、C99(それは99ですか)のVLAでは、strcpyを使用するもう1つの理由があります(mallocも必要ありません)。いつもこれができるわけではありませんが、できる場合はそうするべきです。

  • これはISO標準の一部ではありません(ただし、POSIX標準の一部です。Wizのおかげです)が、R ..が簡単に追加できると述べたように、これは本当に小さな点です。あなたが移植可能なプログラムを書いているのなら、それがすでに定義されているかどうかをどのように伝えるかはわかりません...

これらはもちろん、私自身の理由のいくつかであり、他の理由ではありません。あなたの質問に答えるために、私が知っているコンセンサスはありません。

自分だけのプログラムを作成していて、strdupに問題がないことがわかった場合、それを使用しない理由は、多くのスキルレベルと年齢の多くの人に読まれるプログラムを作成している場合よりもはるかに少なくなります。

2
Seth Carnegie

言及されていないstrdupを嫌う私の理由は、自然なペアのないリソース割り当てであるためです。ばかげたゲームを試してみましょう。私はmallocと言い、あなたはfreeと言います。私はopenと言い、あなたはcloseと言います。私はcreateと言い、あなたはdestroyと言います。私はstrdupと言います....?

実際、strdupの答えはもちろんfreeであり、関数の名前はmalloc_and_strcpyそれを明確にするため。しかし、多くのCプログラマーはそれをそのように考えておらず、strdupは割り当てを解除するためにfreeの反対または「終了」が必要であることを忘れています。

私の経験では、strdupを呼び出すコードでメモリリークを見つけることは非常に一般的です。 strlenmallocstrcpyを組み合わせた奇妙な関数です。

1