Окно/форма WTL аварийно завершает работу после того, как бесконечный цикл сообщений вызывает переполнение стека

У меня есть устаревший проект, в котором мне нужно исправить ошибки, WTL/VC++. Одна из проблем - вылет главного окна (ну и всего приложения, разумеется) после использования клавиш Ctrl+X или Ctrl+Z. У меня нет никаких пользовательских ускорителей, назначенных этим клавишам. Я обнаружил, что «фатальные» комбинации клавиш вызывают бесконечный цикл сообщений с

uMsg == 273 (0x00000111)

который в конечном итоге вылетает с ошибкой переполнения стека:

 Command Code: 5, ID: 29892, HANDLE:  0xe091aFirst-chance exception at 0x007f88fa 
 in <myApp>.exe: 0xC00000FD: Stack overflow.
 Unhandled exception at 0x007f88fa in <myApp>.exe: 0xC00000FD: Stack overflow.

Я просто пропатчил его в функции обработки сообщений -

BEGIN_MSG_MAP (CMDICChildWindowImpl)

    MESSAGE_HANDLER(WM_CREATE, OnCreate)
    MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
    MESSAGE_HANDLER(WM_CLOSE, OnClose)
    MESSAGE_HANDLER(WM_TIMER, OnTimer)

* *

    COMMAND_ID_HANDLER(ID_FILE_NEW, OnNewDownload)
    COMMAND_ID_HANDLER(ID_UPLOAD_FOLDER_SET, OnUploadFolderSet)
    COMMAND_ID_HANDLER(ID_OPEN_RECORD_BY_ID, OnOpenOnline)

* *

    NOTIFY_CODE_HANDLER(HLN_PORTAL_RECORD_DOWNLOAD, OnPortalPageNotify);
    NOTIFY_CODE_HANDLER(HLN_SELCHANGED, OnWebFormNotify);
    if(uMsg == 273)
     return false;
    else
     CHAIN_MSG_MAP(baseClass)

END_MSG_MAP()

Но меня не устраивает этот пластырь, было бы неплохо понять, что происходит, и я действительно хочу, чтобы эти комбинации клавиш выполняли стандартные действия Windows в моей форме, «вырезали» и «отменяли».

больше информации о фатальных сообщениях:

Ctrl+Х -

uMsg 273 целое без знака

wParam 123171 целое число без знака

lParam 0 длинный

lParam 0 длинный

Ctrl+Z -

uMsg 273 целое без знака

wParam 123179 целое число без знака

lParam 0 длинный

Извините, если это не имеет смысла, мое кунг-фу VC++ довольно ржавое; Если бы кто-нибудь мог дать мне подсказку, где искать идеи, это было бы очень признательно.

Спасибо!

O.


person Oleg Ivanov    schedule 28.10.2011    source источник
comment
273 равно WM_COMMAND, и вы, кажется, продолжаете отбрасывать эту команду, пока она не заполнит стек. Ваши фрагменты кода выше не показывают, что именно делается неправильно.   -  person Roman R.    schedule 28.10.2011
comment
Ясно, WM_COMMAND - так что я должен быть осторожен и проверять wParams, чтобы не отфильтровывать другие меню/акселераторы и тому подобное. Спасибо, я должен был быть более настойчивым в поиске кода. Я предполагаю, что он подпрыгивает, потому что он не обрабатывается в «базовых классах» и перенаправляется обратно в «дочерний». Что касается кода - я действительно не знаю, что здесь опубликовать, что помогло бы. Еще раз спасибо, Роман!   -  person Oleg Ivanov    schedule 28.10.2011
comment
Обычный поток операций заключается в том, что COMMAND_ID_HANDLER или COMMAND_HANDLER или любой другой обработчик для WM_COMMAND обрабатывает сообщение и завершает обработку на этом. Возможно, у вас есть то, что этот обработчик запускает некоторую активность, которая генерирует одно и то же уведомление, и оно переходит к переполнению стека. Следовательно, обработчик важен. И у вас также есть стек вызовов с деталями.   -  person Roman R.    schedule 28.10.2011
comment
Великолепно! не было MESSAGE_HANDLER для WM_COMMAND ни в этом окне/классе, ни в его базовых окнах, и была переадресация сообщений по цепочке/перенаправлению, которая вызвала бесконечный цикл. Спасибо за помощь!   -  person Oleg Ivanov    schedule 28.10.2011
comment
Это все еще запах чего-то недосказанного. Я бы сказал, что вам не нужна строка обработчика, и вместо этого вам следует искать строку пересылки, которая размещена неправильно, чтобы завершить циклическую ссылку.   -  person Roman R.    schedule 28.10.2011
comment
точно! строка CHAIN_MSG_MAP(baseClass) передает сообщение базовому классу, у которого не было обработчика WM_COMMAND, но зато был макрос CHAIN_ACTIVETABVIEW_COMMANDS, который делал следующее ::SendMessage(m_hWndActive, uMsg, wParam, lParam), то есть отправлял сообщение обратно в активный окно, с которого все началось — отсюда и бесконечный цикл   -  person Oleg Ivanov    schedule 28.10.2011


Ответы (1)


Нашел это благодаря @Roman R. - в рассматриваемом окне не было обработчика сообщения WM_COMMAND, а в одном из его базовых классов была функция, которая генерировала бесконечный цикл, пересылая сообщение обратно в активное окно . Поэтому я добавил этот обработчик -

        if(uMsg == WM_COMMAND)
          return DefWindowProc(WM_COMMAND, wParam, lParam);

что кажется мне хорошим решением.

Спасибо!

person Oleg Ivanov    schedule 29.10.2011