web-dev-qa-db-ja.com

strcpy_sはどのように機能しますか?

ご存知のとおり、strcpy_sはstrcpyの安全バージョンです。

しかし、それがどのように機能するのだろうか...

いくつかの例を見てみましょう。

strpy_sの宣言:
errno_t strcpy_s(_CHAR * _DEST、size_t _SIZE、const _CHAR * _SRC)

eg1

char dest[5];
char* src = "abcdefg";
strcpy_s(dest,5,src);

アサーションを返します。
これは理解できると思います。_ SIZEを使用して、_ SIZEより多くの文字をコピーできないことを確認してください

しかし、私はこれを理解できません。

char dest[5];
char* src = "abcdefg";
strcpy_s(dest,10,src);

それでもアサーションを取得できますが、どのように発生しましたか?

pS、エラーは:

デバッグアサーションに失敗しました
式:(L "バッファが小さすぎます" && 0)


VS2013

strcpy_sは本体内部のdestのサイズをチェックしますか??そして、それがtrueの場合、どのように_DESTのようなポインターをチェックするのですか?

11
Joey

これは実際には、ポインタへの減衰なしに、実行時にスタック配列のサイズを取得する方法です。

template<typename T, size_t N> 
size_t arrSize(T (&array)[N])  
{
  return N;
}

これをテンプレート参照として送信すると、テンプレートメカニズムによってサイズが推定されます。したがって、次のようなことができます

int myArray[10];
cout << arrSize(myArray); // will display 10

だから私の推測では、これが「安全な」MS strcpy_sはサイズをチェックしています。それ以外の場合、ポインタのみを渡すと、サイズを取得する標準に準拠した方法はありません。

8
vsoftco

DEBUGモードでは、Microsoft APIはバッファを0xfdで埋めるため、オーバーフローをチェックできます。

この関数はコピーされた文字列を切り捨てませんが、例外を発生させます!

Destバッファーのサイズを指定するのは常に困難です(sizeofではなく_countofを使用)。ほとんどの場合、ポインターを使用するときに!

これらの "_s" APIには、標準のものよりも多くの問題があります!!

2
Ananké

destは5文字を超えることはできません。そのため、エラーが発生します。 __SIZE_が原因ではありません。 destが_char*_の場合、十分なメモリを割り当てる必要があります。コンパイルエラーは発生しません。ただし、プログラムでは、destのサイズは固定されており、_strcpy_s_は、strcpyとは異なり、宛先バッファのサイズをチェックします(可能な場合、この場合は、コンパイル時にサイズが定義されているため、チェックできます)。これを読む

http://www.cplusplus.com/forum/beginner/118771/

基本的に_strcpy_s_はstrcpyの「安全な」バージョンであり、オーバーフローすることはできません。標準から:C(2011)およびISO/IEC WDTR 24731-_strcpy_s_:コピーする前に宛先バッファーサイズをチェックするstrcpyのバリアント。内部的には、おそらく_strcpy_s_がsizeof(dest)<SIZEをアサートします。

1
vsoftco

[〜#〜] msdn [〜#〜] 「strcpy_s関数は、strSourceのアドレスの内容を、終端のnull文字を含めて、strDestinationで指定された場所にコピーします。宛先文字列は、ソース文字列とその終端のnull文字を保持するのに十分な大きさである必要があります。strcpy_sの動作は未定義ですソースと宛先の文字列が重複している場合。」

1