我有一个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"); }
wcscpy_s
的文档说明了该函数的调试版本用特殊值0xFE
填充目标缓冲区。
当你调用wcscpy_s(tmp, sizeof(tmp), defaultVal);
你传递的是tmp
缓冲区的大小,但是wcscpy_s
需要字符长度的长度。 因此,传递给wcscpy_s
的长度是它应该是的两倍,而且当tmp
缓冲区被0xfe
覆盖时,即使源字符串( L"Default";
)的长度是缓冲区溢出和未定义的行为小。
所以使用_countof(tmp)
而不是_sizeof(tmp)
。
这就是说,我建议你学习如何使用Visual Studio调试器。
正如Michael Walz的回答中所解释的,由于传递了不正确的缓冲区大小,导致缓冲区溢出。
除了他建议使用_countof(tmp)
而不是sizeof(tmp)
,我想补充一点,在C ++中有一个方便的wcscpy_s()重载, 它会自动推导出正确的缓冲区大小 :
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);
如果你使用这个重载,那么你就_countof
那些错误类型错误的sizeof
/ _countof
。
请注意,这个C ++重载只有在你有像wchar_t tmp[100]
这样的静态缓冲区时才起作用,因为C ++编译器必须能够在编译时计算出缓冲区的大小。 另一方面,当你有指向 动态分配缓冲区的指针时,你必须明确地传递正确的缓冲区大小。