2017-10-10 135 views
3

我的wcscpy_s函数有问题。 wcscpy_s返回我函数的参数(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)'给你在*字节×大小,但它应该是* *元件阵列中的数量。见例如[此'wcscpy_s'参考](https://msdn.microsoft.com/en-us/library/td1esda9.aspx)。 –

回答

2

wcscpy_s的documentgation指出,这一功能的调试版本填充与特殊价值0xFE目标缓冲区。

当您拨打wcscpy_s(tmp, sizeof(tmp), defaultVal);时,您将传递tmp缓冲区的大小,但wcscpy_s需要字符数的长度。因此,你传递给wcscpy_s长度的两倍,只要它应该是,随着tmp缓冲区由0xfe覆盖你得到一个缓冲区溢出和未定义的行为,即使长度,如果源字符串(L"Default";)小。

因此,使用_countof(tmp)代替_sizeof(tmp)

该说的,我建议你学习如何使用Visual Studio调试器。在迈克尔·瓦尔兹的答案已经解释

2

至于,您由于传递不正确的缓冲区大小缓冲区溢出。

除了他使用_countof(tmp),而不是sizeof(tmp)的建议,我想补充一点,在C++还有的wcscpy_s() that automatically deduces the correct buffer size方便的过载:

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

基本上,你可以写更简单这样的代码,这将只是工作:

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); 

如果你使用这种超载,那么你就不会遇到那些错误类型的错误。

注意,这个C++超负荷工作只有当你有像你wchar_t tmp[100]静态缓冲区,作为C++编译器必须能够在编译时找出缓冲区的大小。在另一方面,当你有指针动态 -allocated缓冲区,你必须明确地传递正确的缓冲区大小。