我的wcscpy_s
功能有问题。 wcscpy_s
返回后,我的函数的参数(stringOne
和stringTwo
)无法读取。
这是一个简单的演示来显示问题。
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");
}
答案 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 ++编译器必须能够在编译时中找出缓冲区大小。另一方面,当你有指针到动态分配的缓冲区时,你必须明确地传递正确的缓冲区大小。