在wcscpy_s之后读取字符串字符时出错

时间:2017-10-10 08:55:35

标签: c++ c windows wchar-t wstring

我的wcscpy_s功能有问题。 wcscpy_s返回后,我的函数的参数(stringOnestringTwo)无法读取。 这是一个简单的演示来显示问题。

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

2 个答案:

答案 0 :(得分:2)

wcscpy_s的文档声明此函数的调试版本使用特殊值0xFE填充目标缓冲区。

当您致电wcscpy_s(tmp, sizeof(tmp), defaultVal);时,您传递tmp缓冲区的大小,但wcscpy_s需要字符数的长度。因此,传递给wcscpy_s的长度是它应该的长度的两倍,并且当tmp缓冲区被0xfe覆盖时,您会得到缓冲区溢出和未定义的行为,即使长度也是如此如果源字符串(L"Default";)很小。

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

这就是说,我建议你学习如何使用Visual Studio调试器。

答案 1 :(得分:2)

正如Michael Walz的回答中所解释的那样,传递不正确的缓冲区大小会导致缓冲区溢出。

除了他建议使用_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);

如果您使用此重载,则不会遇到sizeof / _countof不匹配的错误。

请注意,只有当您拥有像wchar_t tmp[100]这样的静态缓冲区时,此C ++重载才有效,因为C ++编译器必须能够在编译时中找出缓冲区大小。另一方面,当你有指针动态分配的缓冲区时,你必须明确地传递正确的缓冲区大小。