在这种情况下,Win32错误码122是良性的吗?

Is Win32 error code 122 somewhat benign in this case?

本文关键字:这种情况下 Win32 错误 误码      更新时间:2023-10-16

GetLastError()返回错误码122 (=ERROR_INSUFFICIENT_BUFFER)

CString str = CString("'") + _T("%s") + CString("'");

但是这只在VS2005下发生,而在VS2015中不会发生。我仍然没有看到内存损坏或任何东西在VS2005和str变量包含正确的值。给出错误代码,这仍然是一个值得关注的问题吗?

发生这种情况的原因似乎是因为宽字符和简单字符串的连接,修复方法是简单地用_T("")包围剩下的两个字符串,这样代码行看起来像:

CString str = CString(_T("'")) + _T("%s") + CString(_T("'"));

但是当原始行中只有一个字符串是Unicode时,错误码122真正意味着什么?到底发生了什么错误,还是在这种情况下更像是一种警告?

GetLastError()仅在某些系统调用返回错误后才有意义。因为你的代码没有任何系统调用,所以GetLastError()可以返回任何东西。

可能您看到的值是上次失败的系统调用的最后一个错误。或者可能是CString类内部发生的一些错误,但它在那里处理。

TL,博士;

在VS 2015中,您可以使用CString("a")(如果设置了Unicode)或CStringW("a")来重现错误

#include <iostream>
#include <atlstr.h>
int main()
{
    CStringW("a");
    DWORD err = GetLastError();
    std::cout << err << "n"; //<= error 122, ERROR_INSUFFICIENT_BUFFER
    return 0;
}

这是因为CString使用WinAPI MultiByteToWideChar将ANSI "a"转换为Unicode L"a"。通过"atlmfcincludecstringt.h"中的源代码进行调试,我们看到在某些地方它调用了以下函数:

static int __cdecl GetBaseTypeLength(_In_z_ LPCSTR pszSrc) throw()
{
    // Returns required buffer size in wchar_ts
    return ::MultiByteToWideChar( _AtlGetConversionACP(), 0, pszSrc, -1, NULL, 0 )-1;
}

由于某种原因,在末尾有一个-1。我不知道为什么会这样,它可能是必要的其他CString函数,但在这种情况下,它最终导致ERROR_INSUFFICIENT_BUFFER错误在下一次调用MultiByteToWideChar。转换可以大致简化为:

int main()
{
    int nDestLength = MultiByteToWideChar(CP_ACP, 0, "a", -1, NULL, 0) - 1;
    wchar_t *pszDest = new wchar_t[32];
    //ERROR_INSUFFICIENT_BUFFER occurs here because nDestLength is short by 1:
    MultiByteToWideChar(CP_ACP, 0, "a", -1, pszDest, nDestLength);
    DWORD err = GetLastError();
    std::cout << err << "n";
    return 0;
}

nDestLength太小,因为它没有考虑空终止符。CString稍后整理,但错误仍然存在。这是不关注GetLastError的一个很好的理由,除非函数失败。

正如您所注意到的,这个错误可以通过使用_T宏来避免,因为CString将不再需要MultiByteToWideChar。或者使用L前缀,或者CString::Format

CString str = CString(L"'") + L"%s" + CString(L"'");