2016-09-01 1 views
0

следующие результаты строки в GetLastError() возврата кода ошибки 122 (= ERROR_INSUFFICIENT_BUFFER)Является ли код ошибки Win32 122 несколько мягким в этом случае?

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

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

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

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

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

+1

ли вам SetLastError (0) как раз перед этой операцией? –

+0

@ IgorR. Нет, но я проверяю значение перед этим вызовом и после него и изменяется от 0 до 122. – zar

+3

Случайное обращение к GetLastError для вещей, которые не документированы в SetLastError при ошибке, приводит к бессмысленным результатам.Конкатенация строк, такая как вы делаете, не приводит к вызову SetLastError, поэтому любое значение, которое вы получаете от GetLastError, не имеет смысла. –

ответ

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, но в этом случае он вызывает ошибку 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"'"); 
+1

* «По какой-то причине в конце есть« -1 ». Я не знаю, почему это так» * - вызов 'MultiByteToWideChar' возвращает число единиц кода, включая завершающий нулевой символ (когда * cbMultiByte * установлен в '-1'). По соглашению реализация 'CString' всегда использует длину без конечного нулевого символа. Для этого необходимо отрегулировать возвращаемое значение 'MultiByteToWideChar'. – IInspectable

+0

@Инспективный, но он должен передать 'strlen (source)' для 'cbMultiByte', если он не хочет считать нулевой ограничитель и не делает вычитания (для обоих вызовов' MultiByteToWideChar'). Вместо этого он проходит -1, чтобы получить счет, включая нуль-терминатор, и два вызова не совпадают. –

+0

'MultiByteToWideChar' не нужно знать количество символов раньше времени. Он выполняет итерацию по всей последовательности, суммируя длины преобразованных кодовых единиц для каждого символа, вплоть до и заканчивая нулевым символом. Явное вызов 'strlen' бесполезно тратит ресурсы, без каких-либо непосредственных выгод. – IInspectable

4

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

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

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

+0

Я могу заверить, что код ошибки действительно генерируется, потому что эта строка я разместил. Я создал новое приложение по умолчанию, в котором ничего больше нет, и добавил кнопку, и этот вызов в событии нажатия кнопки, и я вижу код ошибки 122. Таким образом, что-то уверенное, другого системного вызова нет. – zar

+1

@zar: вы добавили кнопку? Таким образом, есть окно и класс окна и петля mesaage где-то, возможно, в библиотеке MFC или аналогичной. Там много системных вызовов. – rodrigo

+1

@zar Я могу заверить вас, что код ошибки был задан некоторыми деталями реализации и, если необходимо, обработан реализацией. Если CString сам не документирует, что вы должны посмотреть GetLastError() после его использования (а это не так), вы должны игнорировать его. –

 Смежные вопросы

  • Нет связанных вопросов^_^