Почему закрытие созданного окна приводит к коду выхода 134 (0x86) в воспроизводимом примере кода ниже?
Я также обнаружил, что изменение переменной const wchar_t CLASS_NAME[]
приводит к другому коду выхода. Увеличение имени класса на 1 символ увеличивает код выхода на 2, кажется.
Что я ожидал от этого кода, так это код выхода 0, верно? Чем это вызвано?
#include <Windows.h>
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ PWSTR lpCmdLine, _In_ int nShowCmd) {
const wchar_t CLASS_NAME[] = L"AFEWCHARACTERS";
WNDCLASSW wc = {};
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClassW(&wc);
HWND hwnd = CreateWindowExW(
0,
CLASS_NAME,
L"Window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
nullptr,
nullptr,
hInstance,
nullptr
);
if (hwnd != nullptr) {
ShowWindow(hwnd, nShowCmd);
}
MSG msg{};
while (GetMessageW(&msg, nullptr, 0, 0) > 0) {
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
}
Ваш код демонстрирует неопределенное поведение, поскольку в вашей функции wWinMain()
отсутствует требуемый оператор return
после завершения цикла обработки сообщений:
MSG msg{};
while (GetMessageW(&msg, nullptr, 0, 0) > 0) {
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return 0; // or msg.wParam // <-- ADD THIS!
}
Возвращаемое значение wWinMain()
используется для установки кода выхода вызывающего процесса при корректном выходе (т. е. если ExitProcess()
/TerminateProcess()
не вызывались заранее и не было создано необработанное исключение). Согласно документации GetExitCodeProcess():
Эта функция возвращается немедленно. Если процесс не завершен и функция выполнена успешно, возвращается статус
STILL_ACTIVE
(макрос дляSTATUS_PENDING
(minwinbase.h
)). Если процесс завершен и функция выполнена успешно, возвращается одно из следующих значений состояния:
- Выходное значение, указанное в функции
ExitProcess()
илиTerminateProcess()
.- Возвращаемое значение функции
main()
илиWinMain()
процесса.- Значение исключения для необработанного исключения, вызвавшего завершение процесса.
Только main()
(который определен стандартами C/C++ и, следовательно, имеет специальную обработку) может опускать оператор return
, и в этом случае его возвращаемое значение будет неявно равно 0. Любая другая функция с возвращаемым типом, отличным от void
, требует явного return
, иначе возвращаемое значение будет неопределенным.
Соответствующий компилятор должен выдавать диагностику, когда функция с типом возвращаемого значения, отличным от void
, не возвращает значение. Как ни странно, MSVC применяет правила для main к функциям, которые используют один из вариантов WinMain
в качестве своего имени (но затем забывает придумать подразумеваемое возвращаемое значение по умолчанию).
Я беру это обратно: соответствующий компилятор не должен выдавать диагностику, когда функция, возвращающая значение, не возвращает значение. Это просто УБ. Я предполагаю, что MSVC прав здесь, даже если это немного сбивает с толку: он выдаст серьезную ошибку, если какая-либо функция, возвращающая значение, которая не вызывается main
/WinMain
(и варианты), на самом деле не возвращает значение.
я не вижу никакого оператора возврата в вашем
WinMain()