Форум: "Основная";
Текущий архив: 2007.08.05;
Скачать: [xml.tar.bz2];
ВнизВызов функции по таймеру Найти похожие ветки
← →
lexicss © (2007-05-29 11:01) [0]Привет, народ! Вот тут упёрся в одну проблемку, может вы поможете разобрать и решить.
Работаю на Delphi 5 и вот наткнулся на такую ситуацию. Есть у меня одна функция и мне её надо вызвать спустя какой-то интервал времени, делаю это с помощью SetTimer. В чём странность? Так вот: в 98-ой винде работает всё нормально. В XP функция таймера срабатывает дважды, а в 2000-ой мало того что срабатывает функция дважды, так после второго завершения программа вылетает с исключением "Access violation", притом не важно что выполняется в функции(процедуре) вызываемой по таймеру.
Приведу приметивнейший пример
unit Main;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
procedure MyFunc(hWnd: THandle; uMsg: DWord; idEvent: DWord; dwTime: DWord);
implementation
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject);
begin
SetTimer(0,0,5000,@MyFunc);
end;
procedure MyFunc(hWnd: THandle; uMsg: DWord; idEvent: DWord; dwTime: DWord);
begin
if dwTime = 0
then beep;
end;
end.
Проведя некоторые исследования, я заметил такую особенность, если число параметров в вызываемой функции не превышает 3, то такой ситуации не возникает(из ассемблерного кода видно, что если в функции большех трёх параметров, то 4-ый и последующие уже передаются не через регистры, а через стэк). Ещё одна особенность, если процедуру MyFunc вызывать с соглашение stdcall, то тоже всё нормально.
Очень важно узнать почему так? Может здесь какая-то несовместимость Delphi 5 и Windows 2000(и выше)?
И как тогда выкручиваться при использовании SetTimer в Delphi 5, так как программа должна быть универсальной и работать как под 98-ой, как под 2000-ой и др одинаково?
Как я понял : Моя процедура MyFunc является callback API-шной и следовательно нуждается в директиве stdcall. Если я понял что-то не так - поправьте, пожалуйста.
Но всё же остаётся открытым вопрос, почему в Windows 98 эта функция работатет нормально без stdcall, хоть в ней и больше 3-х параметров? Может ещё какие будут варианты объяснения кроме случайности? Если кто что толкового подскажет, буду признателен.
← →
Сергей М. © (2007-05-29 11:09) [1]
> Моя процедура MyFunc является callback API-шной и следовательно
> нуждается в директиве stdcall
Да, нуждается.
> почему в Windows 98 эта функция работатет нормально
Просто тебе повезло.
← →
MBo © (2007-05-29 11:10) [2]>Очень важно узнать почему так?
Потому, что таймерная функция должна точно соответствовать прототипу по числу и типам параметров, и соглашение о вызове для этого прототипа именно stdcall. Так что незачем искать приключений...
← →
VPBar (2007-05-29 11:18) [3]//Очень важно узнать почему так?
Если параметров меньше 3 то функция передает мусор в регистрах но не портит стэк. Если больше 3 то портит стек и из-за этого вылетает ошибка (адрес возврата на стеке ведь тоже хранится, и может быть запорчен).
// Может здесь какая-то несовместимость Delphi 5 и Windows 2000(и выше)?
Никаких несовместимостей.
//И как тогда выкручиваться
Не надо выкручиваться делай правильно - ставь нужное соглашение о вызове (stdcall в данном случае)
← →
lexicss © (2007-05-30 14:04) [4]Вот тока всё же странно чего стэк не рушется в 98-ой и работает нормально без stdcall?
Спасибо, народ. Вы мне помогли.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2007.08.05;
Скачать: [xml.tar.bz2];
Память: 0.46 MB
Время: 0.038 c