Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Потрепаться";
Текущий архив: 2004.11.28;
Скачать: [xml.tar.bz2];

Вниз

Интересно, почему работает следующий код :)   Найти похожие ветки 

 
Piter ©   (2004-11-08 19:38) [0]

procedure TForm1.Button1Click(Sender: TObject);
begin
 SetTimer(0, 0, 1000, Pointer(integer(@TimerProc)+1));
end;

...
procedure TimerProc(Hnd: hwnd; uMsg: UINT; idEvent: UINT; dwTime: DWORD);
begin
 beep;
end;


Как это не удивительно - но ведь пищит :)
Конечно, в конце концов вылезает AV, особенно если что-нибудь поделать с окном приложения... Но интересно - а почему вообще пищит? Я ведь фактически указал неправильный адрес процедуры...

P.S. Ногами не пинайте, просто чистое любопытство! :)


 
Anatoly Podgoretsky ©   (2004-11-08 19:44) [1]

А чего удивительного, ты перешел на команду плюс 1, можешь посмотреть в отладчике, какая команда не выполнилать, наверняка работа со стеком.
А что ты такие зверские эксперименты проводишь над системой, а почему бы тогда не выполнить Pointer(Random(2000000000))); тоже иногда получишь какой то результат и даже возможно без AV


 
Piter ©   (2004-11-08 20:17) [2]

Anatoly Podgoretsky ©   (08.11.04 19:44) [1]
А что ты такие зверские эксперименты проводишь над системой, а почему бы тогда не выполнить Pointer(Random(2000000000)));


ну если при этом вызовется TimerProc я ОЧЕНЬ ОЧЕНЬ сильно удивлюсь.

А вышеприведенный код у меня пару тройка раз по любому beep исполняет.

Вот и интересно почему? Ведь указатель то на функцию НЕВЕРНЫЙ!


 
Nous Mellon ©   (2004-11-08 20:19) [3]


> Вот и интересно почему? Ведь указатель то на функцию НЕВЕРНЫЙ!

Эээ. А что ответ что не выполняется лишь первая команда потому что ты ее пропускаешь не был принят?


 
begin...end ©   (2004-11-08 20:20) [4]

Piter ©   (08.11.04 20:17) [2]

> Вот и интересно почему? Ведь указатель то на функцию
> НЕВЕРНЫЙ!

У тебя есть доказательства, что выполняется ВСЯ функция?


 
Palladin ©   (2004-11-08 20:22) [5]


> Piter ©   (08.11.04 19:38)

зачем ногами.... Ctrl-Alt-C и догадайся сам куда вызов будет...


 
Anatoly Podgoretsky ©   (2004-11-08 21:00) [6]

Piter ©   (08.11.04 20:17) [2]
У тебя вызывается не TimerProc, а TimerProc + 1, а это уже совсем другая функция.

Так ты посмотрел в окне отладчика, куда у тебя осуществляется переход, что именно не выполняется и сделал вывод почему AV?


 
Piter ©   (2004-11-08 23:20) [7]

Anatoly Podgoretsky ©   (08.11.04 21:00) [6]
Так ты посмотрел в окне отладчика, куда у тебя осуществляется переход, что именно не выполняется и сделал вывод почему AV?


НУ насчет AV фиг знает почему... тем более она не сразу возникает. Если с окном вообще ничего не делать - так программа вообще пищит и пищит (минуту точно пищала).

А комманда видать push ebp теряется...

Но тут у меня такое произошло!

НАРОД! КТО ЗНАЕТ - ПОМОГИТЕ!

В общем, ковырялся я тут с этим окном CPU Window, ставил брекпоинты всякие и у меня теперь такой баг вылез - я просто в шоке!!!

В общем, все программы, которые я компилировал - компилируются нормально. Сложные (ну например мой Magic Forum) и простые, например с использованием TTimer. Но только не те, где используется SetTimer!!!

то есть, создание таймера вот таким способом:

TForm1 = class(TForm)
...
   procedure WMTimer(var Msg: TMessage); message WM_TIMER;
...

procedure TForm1.WMTimer(var Msg: TMessage);
begin
 beep;
end;
...

procedure TForm1.Button1Click(Sender: TObject);
begin
 settimer(handle, 1, 1000, nil);
end;


Вполне успешно, все работает нормально!

Но вот создание таймера таким образом:

...
var
 Form1: TForm1;

procedure TimerProc(Hnd: hwnd; uMsg: UINT; idEvent: UINT; dwTime: DWORD);

implementation

{$R *.dfm}

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
begin
 settimer(0, 0, 1000, @TimerProc);
end;

procedure TimerProc(Hnd: hwnd; uMsg: UINT; idEvent: UINT; dwTime: DWORD);
begin
beep;
end;

end.


Приводит к таким интересным результатам!!!

На первой же итерации таймера издается звуковой сигнал и открывается окно CPU! Причем на таком месте, что я даже хрен знает где это находится. Никаких AV! нажимаешь F9 опять издается звуковой сигнал и открывается окно CPU на том же месте! С какого фига оно открывается?
Я уже и перезагружал windows, создавал чистый проект - не помогает! Вот открываетсяокно CPU на этом месте и все! И процедуру обзывал по другому, не TimerProc. И делал две процедуры типа TimerProc - все равно.

ПРИ ЛЮБОМ ВЫЗОВЕ ЛЮБОЙ ПРОЦЕДУРЫ ТАЙМЕРА С ТАКИМ СОДЕРЖАНИЕМ (beep) РАЗДАЕТСЯ ЗВУКОВОЙ СИГНАЛ И ОТКРЫВАЕТСЯ ОКНО CPU!

далшьше - интереснее! Если в обработчике написано вовсе не beep, а что-то иное, да хотя бы ничего:

procedure TimerProc(Hnd: hwnd; uMsg: UINT; idEvent: UINT; dwTime: DWORD);
begin
 //
end;


то при первой же итерации таймера открывается CPU Window и вылезает AV! Просто ахинея!

Что могло случиться с Дельфи?

P.S. Единственное, что я могу вспомнить - я ставил брекпоинты не в самом редакторе кода, а прямо в CPU Window. То есть, не на строчке дельфовой типа Beep, а на таких командах как "push ebp" или типа того. Но я ведь потом перезагружал дельфи, перезагружал винду - глюк остается!

P.S.S. Я знаю, что звучит параноидально - но факт то есть, так все и происходит! Я сам не понимаю... вот именно такие непонятности при вызове функции таймера! Но ведь функцию таймера же виндоус вызывает, не могла же она испортится?
Причем, глюк то только при вызове функции таймера, именно в этой области я тут активно экспериментировал. Но что я мог сделать такого?!

Кстати, если запускать такой EXE"шник не из под отладчика, а просто в винде, то там где только "beep"- все работает нормально, пищит себе и пищит. А вот там, где в процедуре таймера делается что-то другое, но не beep - то процесс просто завершается без всяких AV! Хотя под IDE если запускать вылезает CPU, поверх него AV!

Подскажите хоть что-нибудь - может какие эксперименты провести?

........

Сейчас проверил в XP - EXE"шник программы, которая в функции таймера без beep - не закрывается!
Я вообще ничего не понимаю...

НАРОД! Если не сложно - напишите простейшую программу, которая работает с SetTimer, только обязательно, чтобы в качестве обработчика работала функция, а не посылалось WM_TIMER заголовку окна.

То есть, чтобы вызов таким макаром происходил:

SetTimer(0, 0, 1000, TimerFunction);

а НЕ чтобы так:

SetTimer(Handle, 1, 1000, nil)

Вот! И выложите плиз EXE"шник где-нибудь - очень хочется проверить! Пусть допустим там просто раз в секунду beep исполняется и все! Если вам не сложно!


 
Ihor Osov'yak ©   (2004-11-09 00:20) [8]

а stdcall кто писать будет? Папа Римский?

try it:

procedure TimerProc(Hnd: hwnd; uMsg: UINT; idEvent: UINT; dwTime: DWORD); stdcall;
begin
beep;
end;


 
Ihor Osov'yak ©   (2004-11-09 00:27) [9]

хотя, если параметров в процедуре таймера не анализировать, то ошибка вследствии отсутствия stdcall проявляться не будет.
==
ради любопытсва, скомпилировал без stdcall, запуск под хп  к никаким внешним неприятностям не привел..


 
GuAV ©   (2004-11-09 00:59) [10]

Ihor Osov"yak ©   (09.11.04 0:27) [9]
хотя, если параметров в процедуре таймера не анализировать, то ошибка вследствии отсутствия stdcall проявляться не будет.


Тогда на стек будет положено при вызове четыре слова, а на выходе будет возвращено одно.

Потом при возврате из вызывающей процедуры может передаться не туда куда ожилалось.

Ihor Osov"yak ©   (09.11.04 0:27) [9]
ради любопытсва, скомпилировал без stdcall, запуск под хп  к никаким внешним неприятностям не привел..

наверное "повезло"

Такие вольности со стеком недопустимы.


 
Ihor Osov'yak ©   (2004-11-09 01:37) [11]

2 [10] GuAV ©   (09.11.04 00:59)

Calling conventions
Directive Parameter order Clean-up Passes parameters in registers?
register Left-to-right Routine Yes
pascal Left-to-right Routine No
cdecl Right-to-left Caller No
stdcall Right-to-left Routine No
safecall Right-to-left Routine No

как видим - отличие между pascal и stdcall - только в порядке передачи параметров, но никак в способе очистки стека. То есть при такой вольности будут только неправилно передаваться параметры, сам же указатель стека сбиваться не будет...

Зы.. я, кстати, не агитировал за "вольности". Токмо  изучения ради...


 
Ihor Osov'yak ©   (2004-11-09 01:38) [12]

pascal Left-to-right Routine No
stdcall Right-to-left Routine No


 
GuAV ©   (2004-11-09 01:45) [13]

Ihor Osov"yak ©   (09.11.04 1:37) [11]
Ihor Osov"yak ©   (09.11.04 1:38) [12]

Однако по умолчанию ведь Register.


 
Просто Джо ©   (2004-11-09 02:08) [14]

Ну,сейчас Питер во всех своих процедурах начнет соглашениями о вызовах баловаться... И опять пойдуть "страшные баги" ;)


 
Ihor Osov'yak ©   (2004-11-09 09:37) [15]

2 [13] GuAV ©   (09.11.04 01:45)
сори, да.. ночью иногда соображаловка тормозится..

почему же тогда вылета нет в случае отсутствия stdcall, Наверное ньюансы в реализации отложенного вызова процедуры, которые могут по идее быть разными в разных версиях операционки.. В некоторых вероятнее всего будет..
..В деталях с ньюансами механизма вызова процедуры таймера не разбирался - не было необходимости.. Оно как бы проще работать в соответсвии с документацией и не искаит приключений такм, где совсем эти приключения не нужны..


 
GuAV ©   (2004-11-09 11:46) [16]

Ihor Osov"yak ©   (09.11.04 9:37) [15]
..В деталях с ньюансами механизма вызова процедуры таймера не разбирался - не было необходимости.. Оно как бы проще работать в соответсвии с документацией и не искаит приключений такм, где совсем эти приключения не нужны..

Полностью согласен. И то же самое касается оригинального сабжа.


 
Piter ©   (2004-11-09 19:54) [17]

Ihor Osov"yak ©   (09.11.04 0:20) [8]
а stdcall кто писать будет? Папа Римский?


Блин... вот я лоханулся :) Совсем из головы вылетело :) Сейчас естественно все стало на свои места - а я уж испереживался...

Но прикольно - на w2k глючит, а вот на XP проверял - работает :)



Страницы: 1 вся ветка

Форум: "Потрепаться";
Текущий архив: 2004.11.28;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.51 MB
Время: 0.044 c
1-1100373817
Кириешки
2004-11-13 22:23
2004.11.28
Как загрузить (или работать) с текстовым файлом размером 2,2 гб?


1-1100625546
Neiron
2004-11-16 20:19
2004.11.28
VB to Delphi


4-1097682747
Hmm
2004-10-13 19:52
2004.11.28
isql.exe или как выполнить команду в консольном приложении... ?


3-1098875412
Некто
2004-10-27 15:10
2004.11.28
патч к АДО


6-1095362341
Лев Ландау
2004-09-16 23:19
2004.11.28
Как зателнетить асю?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский