Сейчас на форуме: zds, UniSoft (+5 невидимых)

 eXeL@B —› Программирование —› ошибка в простом диалоге
Посл.ответ Сообщение

Ранг: 85.5 (постоянный)
Активность: 0.040
Статус: Участник

Создано: 24 апреля 2013 19:37
· Личное сообщение · #1

всех приветствую
краткое изложение проблемы:

каркас простого диалога..
если пытаюсь обрабатывать по нажатию цифр/букв считывать из окна, перевести в верхний регистр и вывести в то же окно - утечка стека и крэш.
причем: SetDlgItemText "уходит" в систему и при наличии бряка на
cmp word [wParam], ID_field_in
снова мы тут тормознем, а стек чем-то израсходован и так в цикле до крэша.
если все тоже самое но вывести в соседнее окно - все нормально.
если считывать из окна, перевести в верхний регистр и вывести в то же окно по кнопке GO - все нормально.

голову уже сломал.. ничего не понимаю... может знающие люди что подскажут..
спасибо!

исходник на фасме + ехе в архиве, пасс exelab.ru

3e5b_24.04.2013_EXELAB.rU.tgz - Dialog__.rar



Ранг: 85.4 (постоянный), 51thx
Активность: 0.090
Статус: Участник

Создано: 25 апреля 2013 09:17 · Поправил: drone
· Личное сообщение · #2

не?

Code:
  1. macro  winproc  _name
  2.     {
  3.          proc _name uses ebx esi edi, hWnd, uMsg, wParam, lParam
  4.     }




Ранг: 85.4 (постоянный), 51thx
Активность: 0.090
Статус: Участник

Создано: 25 апреля 2013 09:27 · Поправил: drone
· Личное сообщение · #3

Code:
  1.         cmp       word  [wParam], ID_field_in
  2.         jne       @F
  3.         mov       ecx, dword [wParam]
  4.         shr       ecx, 0x10
  5.         cmp       cx,  0x300
  6.         jne       @F 


почему бы не так?

Code:
  1.         cmp     [wParam],EN_CHANGE shl 16 + ID_field_in
  2.         jnz     @F   


и тут

Code:
  1.          mov       edi, block_Field_out
  2.          mov       esi, block_Field_in
  3.          mov       ecx, 4
  4.          rep       movs dword [edi], dword [esi]


почему бы не так?

Code:
  1.          mov       esi, block_Field_out
  2.          mov       edi, block_Field_in
  3.          mov       ecx, 4
  4.          cld
  5.          rep       movsd




Ранг: 85.5 (постоянный)
Активность: 0.040
Статус: Участник

Создано: 25 апреля 2013 11:47
· Личное сообщение · #4

drone
за вот это
" cmp [wParam],EN_CHANGE shl 16 + ID_field_in
jnz @F "

отдельное спасибо
остальные примеры - тоже полезны, спасибо. но это дело вкуса.

но ключевая проблема/фраза осталась незамеченной:

если пытаюсь обрабатывать по нажатию цифр/букв считывать из окна, перевести в верхний регистр и вывести в то же окно - утечка стека и крэш.
те. в таком виде имеем непонятный цикл + крэш по исчерпанию стека
Code:
  1.          invoke    GetDlgItemText, [hWnd], ID_field_in, block_Field_in, 0x10
  2.          invoke    CharUpper, block_Field_in
  3.          invoke    SetDlgItemText, [hWnd], ID_field_in, block_Field_in





Ранг: 150.3 (ветеран), 175thx
Активность: 0.160.07
Статус: Участник

Создано: 25 апреля 2013 12:34 · Поправил: -=AkaBOSS=-
· Личное сообщение · #5

DMD пишет:
те. в таком виде имеем непонятный цикл + крэш по исчерпанию стека

минут пять вводил разные символы и жмакал кнопку Go - а стэк и ныне там
ошибка сразу должна показаться? после вызова какой апишки?

/ADD попробуй использовать CharUpperBuff вместо CharUpper, вдруг поможет



Ранг: 85.5 (постоянный)
Активность: 0.040
Статус: Участник

Создано: 25 апреля 2013 12:55 · Поправил: DMD
· Личное сообщение · #6

-=AkaBOSS=-

обновил файлы

ошибка завязана на
Code:
  1.         cmp     [wParam],EN_CHANGE shl 16 + ID_field_in     
  2.          jnz     @F
  3.  
  4.          invoke    GetDlgItemText, [hWnd], ID_field_in, block_Field_in, 0x10
  5.          invoke    CharUpper, block_Field_in
  6.          invoke    SetDlgItemText, [hWnd], ID_field_in, block_Field_in


те. если считывать из контролла и тут же в него писать

2495_25.04.2013_EXELAB.rU.tgz - Dialog_sample_error__.rar




Ранг: 527.7 (!), 381thx
Активность: 0.160.09
Статус: Участник
Победитель турнира 2010

Создано: 25 апреля 2013 13:17
· Личное сообщение · #7

ИМХО проблемма не в стеке, а в маршрутизации сообщений.
На одно нажатие кнопки попадаем в этот участок кода 15 раз. Почему???
Stack 6FA0C, 6F4E0, 6EFB4, 6EA88, 6E55C, 6E030, 6DB04, 6D5D8, 6D0AC, 6CB80, 6C654, 6C128, 6BBFC, 6B6D0, 6B1A4

Далее новое нажатие и стек начинает снова со значения 6FA0C.
Утечки нет.

-----
127.0.0.1, sweet 127.0.0.1




Ранг: 85.4 (постоянный), 51thx
Активность: 0.090
Статус: Участник

Создано: 25 апреля 2013 13:38 · Поправил: drone
· Личное сообщение · #8

выкинул все непонятное и перебазировал обработчик, один фиг вылетает после синего экрана от ошибки в MessageBox уже ничего не удивляет

ps. вот такая шняга на си тоже вылетает
Code:
  1. #include <windows.h>
  2. #include "resource.h"
  3.  
  4. char buf[20];
  5.  
  6. int __stdcall _dialogproc(HWND hWnd,UINT wMsg,WPARAM wParam,LPARAM lParam)
  7. {
  8.          switch((WORD)wMsg)
  9.          {
  10.          case WM_INITDIALOG:
  11.                  break;
  12.  
  13.          case WM_COMMAND:
  14.                  if(LOWORD(wParam)==IDC_EDIT1 && HIWORD(wParam)==EN_CHANGE)
  15.                  {
  16.                         GetDlgItemText(hWnd,IDC_EDIT1,buf,16);
  17.                         CharUpper(buf);
  18.                         SetDlgItemText(hWnd,IDC_EDIT1,buf);
  19.                  }
  20.                  break;
  21.  
  22.          case WM_CLOSE:
  23.                  EndDialog(hWnd,NULL);
  24.                  break;
  25.  
  26.          default:
  27.                  return false;
  28.          }
  29.          return true;
  30. }
  31.  
  32. int __stdcall WinMain (HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
  33. {
  34.          HANDLE hMutex=CreateMutex(NULL,TRUE,"dialog");
  35.          if(GetLastError()!=ERROR_ALREADY_EXISTS && hInstance)
  36.                  DialogBoxParam(hInstance,MAKEINTRESOURCE(IDD_DIALOG1),NULL,_dialogproc,NULL);
  37.          ReleaseMutex(hMutex);
  38. }




Ранг: 85.5 (постоянный)
Активность: 0.040
Статус: Участник

Создано: 25 апреля 2013 13:49 · Поправил: DMD
· Личное сообщение · #9

OKOB пишет:
ИМХО проблемма не в стеке, а в маршрутизации сообщений.
На одно нажатие кнопки попадаем в этот участок кода 15 раз. Почему???


полностью согласен: стек - всего лишь внешнее проявление.
вот и мне интересно. почему??? что в чтении из контролла и тут же записи в него такого уникального и только при вводе в него цифры/буквы?? по кнопке GO такой же код работает.
Code:
  1.          cmp       [wParam], ID_OK
  2.          jne       @F
  3.          invoke    GetDlgItemText, [hWnd], ID_field_in, block_Field_in, 0x10
  4.          invoke    CharUpper, block_Field_in
  5.          invoke    SetDlgItemText, [hWnd], ID_field_in, block_Field_in


ps/
такое впечатление что при ассинхронном вводе в контрол следующим шагом в него нельзя писать..
с чего бы это?



Ранг: 85.4 (постоянный), 51thx
Активность: 0.090
Статус: Участник

Создано: 25 апреля 2013 14:01 · Поправил: drone
· Личное сообщение · #10

тут видимо что-то с очередями сообщений самому окну, верно сказано выше

Code:
  1.                  if(LOWORD(wParam)==IDC_EDIT1 && HIWORD(wParam)==EN_CHANGE)
  2.                  {
  3.                         HWND hItem=GetDlgItem(hWnd,IDC_EDIT1);
  4.                         SendMessage(hItem,WM_GETTEXT,16,(LPARAM)buf);
  5.                         CharUpper(buf);
  6.                         SendMessage(hItem,WM_SETTEXT,NULL,(LPARAM)buf);
  7.                  }





Ранг: 150.3 (ветеран), 175thx
Активность: 0.160.07
Статус: Участник

Создано: 25 апреля 2013 14:30
· Личное сообщение · #11

ну, как по мне, тут всё правильно - винда ловит изменение текста в контроле, шлёт сигнал обработчику.
обработчик меняет текст в контроле, винда ОПЯТЬ ловит изменение и ОПЯТЬ вызывает обработчик и так рекурсивно до полного охренения. у меня, правда, это никакой ошибки не вызывает

предлагаю такой костыль:

Code:
  1. case WM_INITDIALOG:
  2.          mov [flag], 0
  3.  
  4.          ...
  5.          <skip>
  6.          ...
  7.  
  8.          cmp [wParam],EN_CHANGE shl 16 + ID_field_in     
  9.            jnz @F
  10.  
  11.          cmp [flag], 1
  12.            je @F
  13.  
  14.          invoke GetDlgItemText, [hWnd], ID_field_in, block_Field_in, 0x10
  15.          invoke CharUpper, block_Field_in
  16.          mov [flag], 1
  17.          invoke SetDlgItemText, [hWnd], ID_field_in, block_Field_in
  18.          mov [flag], 0
  19.  
  20. @@:





Ранг: 164.6 (ветеран), 65thx
Активность: 0.120
Статус: Участник
Волшебник

Создано: 25 апреля 2013 14:41
· Личное сообщение · #12

drone, нужно было ещё приложить заголовок и ресурсы к восьмому посту.
Никаких чудес нет. Быстрее всего имеет место рекурсия с отсылками сообщений контрола самому себе.
Посмотрите трейс сообщений контрола.

-----
Следуй за белым кроликом




Ранг: 85.5 (постоянный)
Активность: 0.040
Статус: Участник

Создано: 25 апреля 2013 15:18
· Личное сообщение · #13

-=AkaBOSS=-
костыль в принципе работает, но приходится по каждому вводу в контролл ставить курсор в крайнее правое положение.. иначе вместо "123456" получим "654321"

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




Ранг: 164.6 (ветеран), 65thx
Активность: 0.120
Статус: Участник
Волшебник

Создано: 25 апреля 2013 15:36
· Личное сообщение · #14

Ненужно костылей. Существует 1000 и один правильный способ. Как вариант можете попробовать ловить WM_SETTEXT, апперкейсить и возвращать FALSE из функции. Скиньте сишные исходники, дома посмотрю.

-----
Следуй за белым кроликом





Ранг: 150.3 (ветеран), 175thx
Активность: 0.160.07
Статус: Участник

Создано: 25 апреля 2013 15:45 · Поправил: -=AkaBOSS=-
· Личное сообщение · #15

DMD пишет:
но приходится по каждому вводу в контролл ставить курсор в крайнее правое положение

не понимаю, почему так получается..
как вариант, можно послать EM_SETSEL:
Code:
  1. invoke GetDlgItem, [hWnd], ID_field_in
  2. invoke SendMessage, eax, EM_SETSEL, 255, 255


DMD пишет:
как лучше всего сделать ввод в контролл, обработать что ввели, на пример- перевели в верхний регистр и вывести в том же контроле?

если нужно просто перевести в верхний регистр, то лучше установи у эдита стиль ES_UPPERCASE

можно обрабатывать WM_CHAR или WM_KEYUP



Ранг: 85.5 (постоянный)
Активность: 0.040
Статус: Участник

Создано: 25 апреля 2013 16:58
· Личное сообщение · #16

neomantneomant пишет:
Скиньте сишные исходники


рад бы.. но это фасм.
если у вас что получится - я переведу на асм



Ранг: 85.4 (постоянный), 51thx
Активность: 0.090
Статус: Участник

Создано: 25 апреля 2013 17:58
· Личное сообщение · #17

проект на си

bba8_25.04.2013_EXELAB.rU.tgz - proj.rar




Ранг: 164.6 (ветеран), 65thx
Активность: 0.120
Статус: Участник
Волшебник

Создано: 25 апреля 2013 20:31 · Поправил: neomant
· Личное сообщение · #18

Так и есть - рекурсия. После отправки контролу WM_SETTEXT контрол уведомляет диалог WM_COMMAND EN_UPDATE и EN_CHANGE. Правильно в данном случае выставить в ресурсах свойство Uppercase контрола в True, чем изобретать костыли или не искать лёгкого пути.

-----
Следуй за белым кроликом


| Сообщение посчитали полезным: DimitarSerg


Ранг: 164.6 (ветеран), 65thx
Активность: 0.120
Статус: Участник
Волшебник

Создано: 25 апреля 2013 21:05 · Поправил: neomant
· Личное сообщение · #19

Если таки не ищем лёгких:
Code:
  1. WNDPROC prvWndProc;
  2.  
  3. LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  4.          switch (uMsg) {
  5.                  case WM_CHAR:
  6.                         wParam = (WPARAM)toupper(wParam);
  7.  
  8.                  default:
  9.                         return CallWindowProc(prvWndProc, hwnd, uMsg, wParam, lParam);
  10.          }
  11. }
  12.          /*
  13.          case WM_COMMAND:
  14.                  if(LOWORD(wParam)==IDC_EDIT1 && HIWORD(wParam)==EN_UPDATE)
  15.                  {
  16.                         GetDlgItemText(hWnd,IDC_EDIT1,buf,16);
  17.                         CharUpper(buf);
  18.                         SetWindowText(GetDlgItem(hWnd, IDC_EDIT1), buf);
  19.                         //SetDlgItemText(hWnd,IDC_EDIT1,buf);
  20.                  }
  21.                  break;
  22.          */
  23.          case WM_INITDIALOG:
  24.                  prvWndProc = (WNDPROC)SetWindowLong(GetDlgItem(hWnd, IDC_EDIT1), GWL_WNDPROC, (LONG)WndProc);
  25.                  break;


-----
Следуй за белым кроликом




Ранг: 85.5 (постоянный)
Активность: 0.040
Статус: Участник

Создано: 25 апреля 2013 22:42
· Личное сообщение · #20

все спасибо за помощь!



Ранг: 85.5 (постоянный)
Активность: 0.040
Статус: Участник

Создано: 26 апреля 2013 10:03 · Поправил: DMD
· Личное сообщение · #21

neomant пишет:
в данном случае выставить в ресурсах свойство Uppercase контрола в True


перевод в верхний регистр - это только как пример. при любой другой обработке введенных символов без "костылей" похоже не обойтись.
какие есть мысли на этот счет?

-=AkaBOSS=-
"костыль" фактически дает двухкратную запись в контролл вывода.
коррекция:
Code:
  1.          invoke    GetDlgItemText, [hWnd], ID_field_in, block_Field_in, 0x10
  2.          invoke    CharUpper, block_Field_in
  3.          mov       [flag], 1
  4.          invoke    SetDlgItemText, [hWnd], ID_field_in, block_Field_in
  5.          mov       [flag], 0
  6.          jmp       .exit_true                                                             


но почему после вывода в контролл ID_field_out "ловим" останов на " mov [flag], 0"??
и в стек указатель на ID_field_in
0006FB74 |00000111
0006FB78 |03000101


[img]img/attach.gif"> <SCRIPT type=text/javascript>dfl("files/","ebb3_26.04.2013_EXELAB.rU.tgz");</SCRIPT> - Sample__Dialog_a_.EXE

ps/
лишние символы в коде - это не ко мне <img src="http://exelab.ruimg/smilies/s1.gif[/img]



Ранг: 138.7 (ветеран), 135thx
Активность: 0.110
Статус: Участник

Создано: 26 апреля 2013 11:09
· Личное сообщение · #22

А почему бы не обработать сообщение WM_CHAR. В wParam будет ASCII код вводимого символа, делай с ним че хошь и отдавай обратно в wParam

| Сообщение посчитали полезным: DMD

Ранг: 85.5 (постоянный)
Активность: 0.040
Статус: Участник

Создано: 26 апреля 2013 13:00
· Личное сообщение · #23

crc1
это не спасет от вывода после обработки в тот же контрол и как следствие рекурсии, если без варианта -=AkaBOSS=-.
видно рекурсию без "костылика" не победить.
похоже, варианты исчерпаны.
мысли еще у кого есть?




Ранг: 150.3 (ветеран), 175thx
Активность: 0.160.07
Статус: Участник

Создано: 26 апреля 2013 14:01
· Личное сообщение · #24

DMD
crc1, кстати, правильно говорит.
если обрабатывать вместо EN_UPDATE - WM_CHAR, можно обойтись без SetWindowText/SetDlgItemTxt и, стало быть, и без рекурсивного вызова обработчика

а насчёт моего костыля - фикс должен выглядеть немного иначе, имхо
см аттач.


90c3_26.04.2013_EXELAB.rU.tgz - Dialog__.zip

| Сообщение посчитали полезным: DMD

Ранг: 85.5 (постоянный)
Активность: 0.040
Статус: Участник

Создано: 26 апреля 2013 14:23
· Личное сообщение · #25

-=AkaBOSS=- пишет:
crc1, кстати, правильно говорит.

согласен, поторопился. попробую применить

-=AkaBOSS=- пишет:
фикс должен выглядеть немного иначе

да, спасибо, хорошо работает.. правда, не привычен "второй проход" в одном обработчике.

похоже, выжали из темы все.
всем спасибо за помощь!




Ранг: 164.6 (ветеран), 65thx
Активность: 0.120
Статус: Участник
Волшебник

Создано: 26 апреля 2013 14:30 · Поправил: neomant
· Личное сообщение · #26

DMD, ещё раз обратите внимание на пост 19. Обработку делайте какую хотите.

-----
Следуй за белым кроликом


| Сообщение посчитали полезным: DMD

Ранг: 85.5 (постоянный)
Активность: 0.040
Статус: Участник

Создано: 26 апреля 2013 15:13
· Личное сообщение · #27

neomant
я опробую, спасибо

параллельно возник вопрос:
можно ли (и как если можно) вывести в edit несколько строк сразу. те.
"
бла-бла-бла
бла-бла-бла
"
размер edit'а - это понятно




Ранг: 150.3 (ветеран), 175thx
Активность: 0.160.07
Статус: Участник

Создано: 26 апреля 2013 15:23 · Поправил: -=AkaBOSS=-
· Личное сообщение · #28

DMD пишет:
можно ли (и как если можно) вывести в edit несколько строк сразу

кажется, можно выставить стиль контрола ES_MULTILINE и выводить строки типа
Code:
  1. str db "bla-bla", 0x0D, 0x0A, "bla-bla", 0




Ранг: 85.5 (постоянный)
Активность: 0.040
Статус: Участник

Создано: 26 апреля 2013 15:40
· Личное сообщение · #29

все работает.

парни, еще раз всем спасибо за помощь!




Ранг: 72.1 (постоянный), 30thx
Активность: 0.050
Статус: Участник

Создано: 28 апреля 2013 00:15
· Личное сообщение · #30

У тебя обработчик при изменении текста контрола вызывает сам себя, снова и снова. Выставляй флаг занятости и проверяй его на входе в обработчик, по выходу - сбрасывай. Это же очевидно?


 eXeL@B —› Программирование —› ошибка в простом диалоге
Эта тема закрыта. Ответы больше не принимаются.
   Для печати Для печати