在这种情况下,Win32错误代码122是否有点温和?

时间:2016-09-01 20:08:09

标签: c++ string unicode mfc

以下行导致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在原始行中的含义是什么?在这种情况下,真正发生了什么错误或更像是警告?

2 个答案:

答案 0 :(得分:4)

GetLastError()仅在某些系统调用返回错误后才有意义。由于您的代码没有任何系统调用,GetLastError()可以返回任何内容。

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

TL; DR;这里没有错误。

答案 1 :(得分:2)

在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"。通过"atlmfc\include\cstringt.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函数可能是必要的,但在这种情况下,它会在下次调用{{1}时导致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