6

手がかりはタイトルにありますが、基本的には strcpy の 800 以上のインスタンスを持つコードを継承しています。新しい関数を作成してから、strcpy を strcpy_mine に置き換えたいと考えています。

そのため、strcpy_mine にどのようなパラメーター リストが含まれるかを調べようとしています。

私は試した:

void strcpy_mine( char* pTarget, const char* const pCopyMe )
{
  const unsigned int lenAlwaysFour = sizeof(pCopyMe ); //:(
  strncpy( pTarget, pCopyMe, lenAlwaysFour );

  //add extra terminator in case of overrun
  pTarget[lenAlwaysFour] = 0;
}

ただし、sizeof は常に 4 pCopyMe はポインターです

私がしたくないことは交換することです

strcpy (buf, pCopyMe);

strncpy (buf, pCopyMe, sizeof(pCopyMe)); buf[sizeof(pCopyMe)] = 0;

何か案は?(strcpy_l は利用できません)

4

7 に答える 7

12

sizeof() は、型のサイズを返します。この場合const char* const、32 ビット マシンでは 4 になります。

私はあなたが欲しいと思うと思いますstrlen()。しかし、それは strncpy 関数を使用する正しい方法ではありません。strncpyの出力バッファのサイズが必要です。

これを修正するには、各呼び出しサイトでコードを調べ、出力バッファーのサイズを計算し、それを引数として に渡す必要がありますstrcpy_mine。strcpy (または strcpy_mine) の呼び出しサイトが出力バッファーのサイズを認識していない場合は、バッファーを割り当てる場所をコード内で逆方向に検索し、サイズを strcpy サイトに渡す必要があります。 .

基本的に、同じ引数を取る strcpy の代わりにドロップインを書くことはできず、最初に strncpy を生成した問題 (およびそれを超えるより良い置換) を回避したいと考えています。strncpy と同じ引数を取る関数を作成できますが、結果が null で終了することを保証します - OpenBSD の strlcpy()関数の実装を見てください。しかし、最初のステップは、呼び出し元サイトを変更して、出力バッファー サイズの情報を渡す必要があります。

于 2009-06-04T15:04:17.637 に答える
4

呼び出しサイトがどのように見えるかに応じて、多くの場合、ほとんどのケースは単純なテンプレートで処理できます。

#include <string.h>

template <int bufferSize>
void strcpy_mine( char (&pTarget)[bufferSize], const char* const pCopyMe )
{
  strncpy( pTarget, pCopyMe, bufferSize-1 );

  //add extra terminator in case of overrun
  pTarget[bufferSize-1] = 0;
}

int main()
{
  char buf[128];
  strcpy_mine(buf,"Testing");
  return 0;
}

Microsoft Visual Studio 2005 以降を使用している場合は、Microsoft 実装のセキュア テンプレート オーバーロードを参照してください。

于 2009-06-04T19:33:06.453 に答える
2

少し周辺的なものかもしれませんが、誰もそれについて言及しておらず、タイトルで誇示されているため、(合法的に)と呼ばれるグローバル関数を作成することはできませんstrcpy_mine()

名前がで始まる関数の「名前空間」はstr、標準ライブラリ用に予約されています。たとえば、この質問に対する受け入れられた回答を参照してください。

于 2009-06-04T19:41:39.633 に答える
2

strcpy_mine の strncpy と同じパラメーター リストを使用できますが、結果が常に null で終了するように記述します。それほど難しいことではないはずです。

ただし、問題の 1 つは、strcpy() を呼び出す既存のコードの一部も、バッファーのサイズを認識していない可能性があることです。

于 2009-06-04T15:05:00.037 に答える
1

ダグラス・リーダーの言うとおりです。すべてのインスタンスで適切で適切なバッファ長を渡すという単調な作業を喜んで行わない限り、strcpy を置き換える有用性には限界があります。それは大変な仕事です!

良いニュースは、それだけの価値があるということです! 数年前、私はいくつかの C++ プロジェクトに参加しましたが、それらは遅く、バグが多く、信頼性がありませんでした。strcpy と strlen を禁止すると宣言し、プロジェクトから 2 ~ 3 日かけてカスタムの strncpy/strnlen に置き換えることで、これらすべてのプロジェクトで突然、数時間ではなく数日実行できるようになりました。また、画面表示やログ ファイルに多くの切り捨てられた文字列が表示されることも確認しました。これにより、切り捨ての問題 (以前はクラッシュの問題) を追跡するために必要な手がかりが得られました。

これを行いたくない場合は、NULL の両方のポインター パラメーターをチェックし、文字列コピーの最大サイズを制限し、境界に到達するたびにログを記録するだけで、はるかに小さなメリットしか得られません。文字列が適切に null で終了されていない場合、strlen は喜んでクラッシュするため、どちらのパラメーターの strlen も実行しないでください。

現在、新しいプロジェクトでは優れた文字列オブジェクトが使用されていますが、使用されていないレガシー コードがたくさんあります。

于 2009-06-04T17:20:12.553 に答える
0

他の人が上で言ったように、宛先バッファーのサイズをパラメーターとして渡す必要があります。

strncpy()これは一種のトピック外ですが、 を使用した後、バッファの最後の文字を null に設定する必要があることを指摘したいだけです。これは、長さよりも小さいインデックス 1 (バッファの長さではありません)を持ちます。 :

strncpy (buf, pCopyMe, buflen); buf[buflen - 1] = '\0';

またはstrncat()、空の文字列で使用して、1 少ない長さを渡すこともできます。これにより、文字列が null で終了することが保証されます。

buf[0] = '\0'; strncat (buf, pCopyMe, buflen - 1);
于 2009-06-04T16:48:26.740 に答える
0

また、複数の編集を避けるためにマクロを使用することもできます。または、スクリプトを使用して編集を自動化します。

于 2009-06-04T15:33:33.223 に答える