2017-10-10 68 views
3

wcscpy_s関数に問題があります。 wcscpy_sの後に、my関数のパラメータ(stringOnestringTwo)が読み込めません。 問題を示す簡単なデモです。wcscpy_sの後の文字列の読み込みエラー

void testFunc(LPCWSTR stringOne, LPCWSTR stringTwo) { 

    wchar_t* defaultVal = L"Default"; 

    wchar_t tmp[100]; 

    int lenBefore = wcslen(stringOne); // Works 

    auto result = wcscpy_s(tmp, sizeof(tmp), defaultVal); 

    int len = wcslen(tmp); 

    int len2 = wcslen(stringOne); // Throws Exception Access violation 
} 


int main() { 
    testFunc(L"Test", L"Test"); 
} 
+1

問題は、 'sizeof(tmp)'は* bytes *のサイズを与えますが、配列の*要素数*でなければなりません。例えば、 [この 'wcscpy_s'リファレンス](https://msdn.microsoft.com/en-us/library/td1esda9.aspx)。 –

答えて

2

この関数のデバッグバージョンは特別な値0xFEで宛先バッファを埋めることwcscpy_s状態のdocumentgation。

wcscpy_s(tmp, sizeof(tmp), defaultVal);に電話するときは、tmpバッファのサイズを渡しますが、wcscpy_sには長さが必要です。したがって、wcscpy_sに渡す長さは2倍になり、tmpバッファが0xfeで上書きされるため、ソース文字列(L"Default";)の長さが短くても、バッファオーバーフローや未定義の動作が発生します。

_sizeof(tmp)の代わりに_countof(tmp)を使用してください。

これは、Visual Studioデバッガの使い方を学ぶことをお勧めします。

2

Michael Walzの答えですでに説明したように、不適切なバッファサイズを渡すことによってバッファオーバーフローが発生しています。

template <size_t size> 
errno_t wcscpy_s( 
    wchar_t (&strDestination)[size], 
    const wchar_t *strSource 
); // C++ only 

基本的に、あなたが書くことができます。

_countof(tmp)代わりのsizeof(tmp)を使用しての彼の提案に加えて、私はC++wcscpy_s() that automatically deduces the correct buffer sizeの便利なオーバーロードがありますでそれを追加したいです

wchar_t tmp[100]; 

// Use the C++-only template overload of wcscpy_s 
// that automatically deduces the destination buffer size 
auto result = wcscpy_s(tmp, defaultVal); 
0:うまく動作します。このような 単純コード、

このオーバーロードを使用すると、sizeof/_countofの不一致のバグの影響を受けません。 C++コンパイラはコンパイル時でバッファサイズを把握することができなければならないとして、このC++オーバーロードは、あなたがあなたのwchar_t tmp[100]のような静的なバッファを持っている場合にのみ機能することを

は注意してください。一方、ポインタを動的にに割り当てた場合、正しいバッファサイズを明示的に渡す必要があります。

関連する問題