CString赋值正在改变GetLastError()

时间:2018-06-11 19:36:16

标签: c++ windows mfc

我正在使用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的某些早期版本中为此提供警告/错误,但现在似乎没有,所以也许我记错了。

2 个答案:

答案 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