在wcscpy_s之后读取string的字符时出错

我有一个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"); } 

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 ++编译器必须能够在编译时计算出缓冲区的大小。 另一方面,当你有指向 动态分配缓冲区的指针时,你必须明确地传递正确的缓冲区大小。