При создании потока функцией CreateThread создается поток, в нем инициализируются локальные переменные(вместе со структурами примерно 8 кб), затем идет вызов подпрограммы, в которой инициализация переменных приводит к краху приложения. Поток создается в длл, под отладчиком все работает замечательно. Если перед вызовом подпрограммы вывести мессаджбокс то по его закрытию приложение продолжает работу без проблем... Код длл: Код (Text): Creating_ars struct Ip DB 128 dup(?) Port DB 128 dup(?) RemIP DB 128 dup(?) Number DB 128 dup(?) User DB 128 dup(?) CID DB 128 dup(?) NUM DB 128 dup(?) Expir DB 128 dup(?) Auth DB 256 dup(?) Data DB 1536 dup(?) tag DB 128 dup(?) intag DB 128 dup(?) port dd ? Creating_ars ends Parsing_ars struct Typ db 128 dup(?) From db 128 dup(?) To db 128 dup(?) VIA db 128 dup(?) cyseq db 128 dup(?) Auth db 256 dup(?) tag db 128 dup(?) intag db 128 dup(?) Contact db 128 dup(?) Call_ID db 128 dup(?) ToNum db 128 dup(?) Expir db 128 dup(?) Parsing_ars ends Ringing struct hiThr dd ? Number db 16 dup (?) Ringing ends InitThread struct AddrOf dd ? ;адрес структуры CHN DD ? ;номер канала Evnt dd ? ;Event управления потоком StopEv dd ? ;Event остановки потоков isFree dd ? ;flag освобождения канала EventSt dd ? ;Event ownPort dd ? ;порт управления на клиенте RemPort dd ? ;порт управления на сервере SDPport dd ? ;порт для РТП потока s dd ? ;socket для управления sSDP dd ? ;socket для РТП потока hClb dd ? ;колбэк функция regTm dd ? ;время регистрации fName dd ? ; имя файла для проигрывания User DB 32 DUP (?) ; Имя пользователя Pass DB 32 DUP (?) ; Пароль SDPIP db 32 dup (?) ; адрес для РТП потока ownIP db 32 dup (?) remIP db 32 dup (?) CID db 128 dup (?) datas db 2048 dup(?) ;передаваемые в поток данные InitThread ends ProbeRing proc Number:dword,fName:dword LOCAL rin:Ringing,TID:InitThread LOCAL chn:dword,td:dword mov chn,0 .while TRUE mov eax,maxChn cmp chn,eax je m2 mov eax,4 mov ecx,chn mul ecx lea ebx,ManageTh add ebx,eax mov eax,[ebx] mov td,eax invoke RtlMoveMemory,addr TID,td,sizeof TID cmp TID.isFree,0 jne m1 invoke CreateEvent,0,TRUE,FALSE,0 mov TID.Evnt,eax m2m TID.fName,fName mov ebx,TID.AddrOf invoke RtlMoveMemory,[ebx],addr TID,sizeof TID invoke lstrcpy,addr rin.Number,Number m2m rin.hiThr,TID.CHN invoke CreateThread,0,0,addr RingOut,addr rin,0,0 cmp eax,0 je m2 invoke CloseHandle,eax invoke WaitForSingleObject,TID.Evnt,INFINITE mov eax,chn ret m1: inc chn .endw m2: mov eax,-1 ret ProbeRing endp RingOut proc parm:dword LOCAL CID1 [64]:byte,CID [64]:byte LOCAL Parse:Parsing_ars,User [16]:byte,PromTAG [32]:byte LOCAL TID:InitThread,ca:Creating_ars LOCAL EP [2]:dword,rin:Ringing LOCAL td:dword,i:dword,hClb:dword,TNO:dword LOCAL ress:dword,tHR:dword invoke RtlZeroMemory,addr ca,sizeof ca invoke RtlZeroMemory,addr rin,sizeof rin invoke RtlZeroMemory,addr TID,sizeof TID invoke RtlZeroMemory,addr Parse,sizeof Parse invoke RtlZeroMemory,addr User,sizeof User invoke RtlZeroMemory,addr PromTAG,sizeof PromTAG invoke RtlZeroMemory,addr CID1,sizeof CID1 invoke RtlZeroMemory,addr CID,sizeof CID invoke RtlZeroMemory,addr EP,sizeof EP invoke RtlMoveMemory,addr rin,parm,sizeof rin INVOKE LocalAlloc,LMEM_FIXED OR LMEM_ZEROINIT,2048 INVOKE LocalLock,eax mov ress,eax mov eax,4 mul rin.hiThr lea ebx,ManageTh add ebx,eax mov eax,[ebx] mov td,eax invoke RtlMoveMemory,addr TID,td,sizeof TID ChistInv: invoke GetTickCount invoke lstrcpy,addr CID1,str$(eax) invoke GetTickCount invoke lstrcpy,addr CID1+8,str$(eax) invoke procMD5hash,addr CID1,32 invoke lstrcpyn,addr CID,addr CID1,32 m2m hClb,TID.hClb invoke EnterCriticalSection,addr CRS inc NumberReq invoke LeaveCriticalSection,addr CRS invoke RtlZeroMemory,addr ca,sizeof ca m2m ca.port,TID.s invoke lstrcpy,addr ca.Ip,addr TID.ownIP invoke lstrcpy,addr ca.Port,str$(TID.ownPort) invoke lstrcpy,addr ca.NUM,str$(NumberReq) invoke lstrcpy,addr ca.RemIP,addr TID.remIP invoke lstrcpy,addr ca.User,addr TID.User invoke lstrcpy,addr ca.CID,addr CID invoke lstrcpy,addr TID.CID,addr ca.CID invoke lstrcpy,addr ca.Number,addr rin.Number invoke lstrcpy,addr ca.tag,CTXT("tag=") invoke lstrcat,addr ca.tag,addr PromTAG invoke lstrcpy,addr ca.Expir,str$(TID.regTm) MOV ca.Auth,0 MOV ca.tag,0 MOV ca.intag,0 ;invoke MessageBox,0,0,0,MB_OK invoke CreateInvite,addr ca invoke lstrcpy,ress,eax ..... ret RingOut endp CreateInvite proc CA:dword LOCAL Result [2048]:byte LOCAL ca:Creating_ars LOCAL Parse:Parsing_ars LOCAL Result1 [512]:byte invoke RtlZeroMemory,addr ca,sizeof ca invoke RtlMoveMemory,addr ca,CA,sizeof ca invoke RtlZeroMemory,addr Result,sizeof Result invoke RtlZeroMemory,addr Result1,sizeof Result1 invoke RtlZeroMemory,addr Parse,sizeof Parse ... ret RingOut endp
Код (Text): mov eax,4 mul rin.hiThr ;<--Не совсем понятно, ты обращаешься к перменной в стеке другого потока? lea ebx,ManageTh add ebx,eax
Скажем проще Код (Text): WndProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM mov eax,uMsg .if eax==WM_INITDIALOG push hWin pop hWnd invoke CreateThread,0,0,addr prose,0,0,0 .elseif eax==WM_COMMAND mov eax,wParam and eax,0FFFFh .if eax==IDM_FILE_EXIT invoke SendMessage,hWin,WM_CLOSE,0,0 .elseif eax==IDM_HELP_ABOUT invoke ShellAbout,hWin,addr AppName,addr AboutMsg,NULL .endif ; .elseif eax==WM_SIZE .elseif eax==WM_CLOSE invoke DestroyWindow,hWin .elseif uMsg==WM_DESTROY invoke PostQuitMessage,NULL .else invoke DefWindowProc,hWin,uMsg,wParam,lParam ret .endif xor eax,eax ret WndProc endp prose proc param:dword LOCAL mi [18024]:byte invoke pros2,0 ret prose endp pros2 proc param:dword invoke MessageBox,0,0,0,MB_OK ret pros2 endp
OFFSIDE Видимо выскакиваешь за сторожевую страницу стека. При выделении больших объемов локальных переменных нужно пробежаться по страницам стека "сверху вниз" от ebp к esp, читая по одному дворду из каждой страницы
leo Спасибо, проблема решена. Очень плохо, что компилятор или система не справляется с данной задачей.
Смотря какой компилятор В языках высокого уровня код probe_stack вставляется автоматически, если размер локальных переменных превышает 4К. Ну а на асме ес-но все приходится делать ручками, хотя в принципе при использовании макросов LOCAL\locals можно было бы делать подсчет общего размера локальных переменных и при необходимости вставлять код probe_stack PS: система ес-но этим заниматься не должна, т.к. использование сторожевой страницы стека помимо обеспечения его динамического роста по мере необходимости, также дает доп.защиту от ошибок
Насколько я понимаю, в ebp и esp как раз и находится размер локальных переменных. По поводу системы можно было бы и поспорить. А компилятор масма хотелось бы и подновить.
И что ? Вставлять probe_stack в каждую функцию ? По хорошему размер нужно анализировать не в рантайме, а на этапе компиляции и вставлять probe_stack только в случае необходимости (что собс-но высокоуровневые компилеры и делают) Можно, но бесполезно По сложившейся традиции стек растет сверху вниз и для экономии памяти винда обеспечивает динамический рост стека при обращении к сторожевой странице, передвигая ее вниз. Доступ к страницам ниже сторожевой запрещен и добраться до них можно только последовательно перемещая сторожевую страницу