Является ли Win32 код ошибки 122 несколько доброкачественным в этом случае?

Следующая строка приводит к GetLastError() вернуть код ошибки 122 (= ERROR_INSUFFICIENT_BUFFER)

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

Но это происходит только под VS2005 и не происходит в VS2015. Тем не менее я не вижу повреждения памяти или что-нибудь в VS2005 и str переменная содержит правильное значение. Это все еще проблема, о которой нужно беспокоиться, дайте код ошибки?

Причина, по которой это происходит, заключается в объединении строк широких символов и простых символов, и исправление состоит в том, чтобы просто распределить обе оставшиеся строки с помощью _T("") поэтому строка кода будет выглядеть так:

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

Но что на самом деле означает код ошибки 122 в исходной строке, когда только одна строка была Unicode? Что плохого действительно произошло или это больше похоже на предупреждение в этом случае?

0

Решение

В VS 2015 вы можете воспроизвести ошибку с CString("a") (если установлен Юникод) или просто 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 функции, но в этом случае это в конечном итоге вызывает 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"'");
2

Другие решения

GetLastError() имеет смысл только после того, как какой-то системный вызов вернул ошибку. Поскольку в вашем коде нет системного вызова, GetLastError() может вернуть все что угодно.

Возможно, значение, которое вы видите, является последней ошибкой последнего системного вызова, который не удался. Или, может быть, какая-то ошибка произошла изнутри CString класс, но он обрабатывается там.

TL; DR; Здесь нет ошибок.

4

По вопросам рекламы [email protected]