我正在使用MFC CString
对象作为字符串。我遇到一个问题,即设置CString
会导致GetLastError()
意外设置为某个问题。
以下是显示问题的问题的简化版本:
CString csTest;
DWORD dwLastError = 0;
SetLastError(0);
csTest = _T("test");
dwLastError = GetLastError(); // dwLastError is still 0, as expected
csTest = "another test"; // Not using TCHAR
dwLastError = GetLastError(); // dwLastError now set to 122, "The data area passed to a system call is too small."
我可以使用Visual Studio 2015重现此问题,创建一个全新的MFC项目(基于Dialog),并在其创建的对话框的OnInitDialog()
函数中添加此代码。
我知道第一个字符串是TCHAR
,在此项目中默认为WCHAR
。因此CString
的{{1}}赋值运算符似乎导致问题。
有没有办法解决这个问题?获取编译器警告以通知我char*
分配而不是char*
的方法?我认为它曾经在Visual Studio的某些早期版本中为此提供警告/错误,但现在似乎没有,所以也许我记错了。
答案 0 :(得分:4)
您可以将宏_CSTRING_DISABLE_NARROW_WIDE_CONVERSION
定义为documented来禁用隐式窄范围转化。
但这只是帮助您解决真正的问题:您只是为时太晚调用GetLastError
。只有在您调用另一个调用时,它的返回值才有效。不要那样做。
现在,即使您成功阻止了任何转换,CString
实现仍然需要分配内存。如果运气不佳,operator new
(调用malloc
)必须联系操作系统'内存管理功能。
解决方案很简单:只有当文档告诉您它将返回有效值时才调用GetLastError
,并且不要散布对任何的任何调用功能。
答案 1 :(得分:1)
将ANSI分配给CStringW
时,会调用WinAPI MultiByteToWideChar
。它有点类似于以下内容:
csTest = "a"; // <- step in to this line with debugger
->
wchar_t *buf = new wchar_t[10];
MultiByteToWideChar(CP_ACP, 0, "a", -1, buf, 1);
//Error 122, ERROR_INSUFFICIENT_BUFFER
//MultiByteToWideChar is expecting 2, not 1, for len
DWORD err = GetLastError();
delete[]buf;
发生此问题是因为CString
使用"a"
的长度而不考虑空字符。 MultiByteToWideChar
设置错误。
CString
稍后修复了问题,但仍然设置了GetLastError
。
只需使用csTest = L"a";
即可避免转换。或csTest = CA2W("a");
否则GetLastError
不应以这种方式使用。在WinAPI函数失败后立即使用GetLastError
。
测试:
#include <Windows.h>
#include <AtlStr.h>
int main()
{
DWORD err;
CStringW str;
wchar_t *buf = new wchar_t[10];
int len = MultiByteToWideChar(CP_ACP, 0, "a", 1, NULL, 0);
MultiByteToWideChar(CP_ACP, 0, "a", -1, buf, len);
err = GetLastError();
printf("MultiByteToWideChar error %d\n", err);
delete[]buf;
//Below is wrong usage of GetLastError(), it's only for this discussion...
SetLastError(0);
str = "a";
err = GetLastError();
printf("assignment operator error %d\n", err);
SetLastError(0);
str = CA2W("12345");
err = GetLastError();
printf("CA2W error %d\n", err);
return 0;
}
输出:
MultiByteToWideChar error 122
assignment operator error 122
CA2W error 0