Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

WaitForMultipleObject, Event, ReadDirectoryChangesW, AV


Страницы:   1 2

Анонимщик1 ©   (2007-03-11 23:45:00) 

Я пытаюсь мониторить изменения в каталоге. Все, вроде бы, выходит, если бы не одно "но". Как только вызов функции оказывается
в блоке try, возникает AccessViolation. Не могу понять, с чем это может быть связано. Не может ли кто растолковать?
Для получения AV достаточно раскомментировать закомментированные строки.


unit main;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls;

type
 TForm1 = class(TForm)
   Button1: TButton;
   procedure FormCreate(Sender: TObject);
   procedure Button1Click(Sender: TObject);
 private
   { Private declarations }
   FhSpyDir: THandle;
   FhDirChangeEvent  : THandle;
   FSpyBufArray  : array[0..4096] of byte;
   function InitReadDirCh: boolean;
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

const
 FILE_LIST_DIRECTORY = $0001;

procedure TForm1.FormCreate(Sender: TObject);
begin
 FhDirChangeEvent := CreateEvent(nil, false, false, nil);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 rez : dword;
 pStpChgHandles : TWOHandleArray;
 i: Integer;
 last: Cardinal;
begin
 pStpChgHandles[0] := FhDirChangeEvent;

 FhSpyDir := CreateFile(PAnsiChar('C:\!TEST!'),
                        FILE_LIST_DIRECTORY,FILE_SHARE_READ or
                        FILE_SHARE_DELETE,
                        nil,
                        OPEN_EXISTING,
                        FILE_FLAG_BACKUP_SEMANTICS or FILE_FLAG_OVERLAPPED,
                        0);
 if FhSpyDir = INVALID_HANDLE_VALUE then
   Exit;

 if InitReadDirCh then
 begin
//    try
     rez := WaitForMultipleObjects(1, @pStpChgHandles, false, INFINITE);
     if rez = WAIT_OBJECT_0+1 then
     begin

     end;
//    finally
     last := GetLastError;
     OutputDebugString(PChar(SysErrorMessage(last)));
     ShowMessage(SysErrorMessage(last));
//    end;
 end;
end;

function TForm1.InitReadDirCh: boolean;
var
 I     : Integer;
 OVPD  : OVERLAPPED;
 p: Pointer;
begin
 result := true;
 OVPD.Internal := 0;
 OVPD.InternalHigh := 0;
 OVPD.Offset := 0;
 OVPD.OffsetHigh := 0;
 OVPD.hEvent := FhDirChangeEvent;
 if not ReadDirectoryChangesW(FhSpyDir, @FSpyBufArray,
                       SizeOf(FSpyBufArray),
                       false,
                       FILE_NOTIFY_CHANGE_LAST_WRITE,
                       nil,
                       @OVPD,
                       nil)  then
   Result := false;
end;

end.


Анонимщик1   (2007-03-12 10:33:00) [21]

> Более того, я подозреваю, что ты неверно понимаешь назначение и логику работы finally-конструкций.

Пусть даже так. Но вопрос этим не снимается.
Возникновение ошибки было замечено случайно (try-finally в этом месте действительно не нужен), но все же непонятна причина, из-за которой она возникает.


Анонимщик1   (2007-03-12 10:31:00) [22]

> А может и не он вовсе ?
Может, и не он. Но только если этот охраняемый блок не вводить, то и AV не возникает. А возникает он и с отладчиком, и без отладчика.

> И кстати, код в блоке finally - точно такой же обычный код, что и в любом ином месте программы, и исключения в этом блоке точно так же возможны.

Да, да только вызов ShowMessage приводит к возниконовению AV крайне редко (хотя и не буду настаивать, что никогда; для оправдания скажу, что я пробовал в разных конфигурациях).


Сергей М.   (2007-03-12 10:29:00) [23]

Более того, я подозреваю, что ты неверно понимаешь назначение и логику работы finally-конструкций.


Сергей М.   (2007-03-12 10:27:00) [24]


> Меня не устраивает, что AV вызывает именно охраняемый блок


А может и не он вовсе ?
Как ты определил, что AV возникает именно в finally-блоке, если не с помощью пошаговой трассировки кода средствами встр.отладчика ?

И кстати, код в блоке finally - точно такой же обычный код, что и в любом ином месте программы, и исключения в этом блоке точно так же возможны.


Сергей М.   (2007-03-12 10:23:00) [25]


> боюсь, если в finally ничего не написать, то оптимизатор
> сделает что-то такое, что ошибка не проявится


Какая ошибка-то ? И как она должна, по-твоему, "проявиться" ?


Сергей М.   (2007-03-12 10:20:00) [26]


> if rez = WAIT_OBJECT_0+1 then


Эта строчка тоже лишена смысла - в твоем случае if-выражение никогда не примет True-значение, потому что ты ожидаешь всего один объект, сигнал которого определяется по WAIT_OBJECT_0, а не WAIT_OBJECT_0+1


Анонимщик1   (2007-03-12 10:19:00) [27]

> Сергей М.
> Ну а зачем тогда этот код, если "согласен" ?)
Если спрашиваете, отвечу: да просто потому, что глюк странный, боюсь, если в finally ничего не написать, то оптимизатор сделает что-то такое, что ошибка не проявится.

>Отладчик тебе на что дан ?
>Бери его в руки и выясняй конкретную строку, вызывающую исключение.
Я прошу прощения, но этим я уже два дня позанимался. Кроме того, что это какой-то глюк компилятора, ничего придумать не могу. Меня не устраивает, что AV вызывает именно охраняемый блок. Я вижу в этом некую странность и поэтому попросил вас (и Вас лично, Сергей) помочь разобраться.


Сергей М.   (2007-03-12 10:14:00) [28]


> Анонимщик1   (12.03.07 10:09) [8]


> Согласен


Ну а зачем тогда этот код, если "согласен" ?)


> этого не произошло - все по-прежнему


Отладчик тебе на что дан ?
Бери его в руки и выясняй конкретнуюстроку, вызывающую исключение.


Анонимщик1   (2007-03-12 10:09:00) [29]

> Сергей М.
> И вообще - код, вынесенный тобой в finally попросту лишен смысла.
Согласен

> Закомментарь вызов OutputDebugString и удивись - AV исчез
А вот этого не произошло - все по-прежнему. У меня WinXP, я администратор, никаких особенностей, препятствующих работе OutputDebugString нет, тем более, что в таком случае ошибка была бы связана с нарушением прав доступа.


Сергей М.   (2007-03-12 10:00:00) [30]


> Анонимщик1   (12.03.07 09:50) [5]


А ты выполнил условия, необходимые для ожидаемой тобой функциональности в работе OutputDebugString ?

Закомментарь вызов OutputDebugString и удивись - AV исчез.

И вообще - код, вынесенный тобой в finally попросту лишен смысла.


MBo   (2007-03-12 09:51:00) [31]

>В Windows.pas он объявлен.
А, ясно. Я подумал - вдруг динамический


Анонимщик1   (2007-03-12 09:50:00) [32]

> Джо
Сорри за несуразности, код я выдирал из готового проекта, поэтому упрощал где мог и кое-чего пропустил.
Что касается GetLastError, то не знаю, что за нонсенс Вы увидели.

> Сергей М.
Ошибка возникает не на WaitForMultipleObject (кстати, этот вызов можно заменить и на WaitForSingleObject), а при входе в блок finally, какэто ни странно. Если try-finally отсутствует, то и AV не возникает.

Собственно, для проверки моего утверждения достаточно создать небольшой тестовый проект. Вы бы проверили.


Сергей М.   (2007-03-12 09:36:00) [33]


> MBo ©   (12.03.07 09:35) [3]


В Windows.pas он объявлен.
Массив из 64-х хэндлов.


MBo   (2007-03-12 09:35:00) [34]

TWOHandleArray - что за тип?


Сергей М.   (2007-03-12 09:20:00) [35]


> Анонимщик1   (11.03.07 23:45)


Что, прямо на строчке с вызовом WaitForMultipleObjects() возникает AV ?
Не верю ...


Джо   (2007-03-12 03:18:00) [36]

Вообще, весь код какой-то странный.
1. Кто будет проверять возвращаемое значение CreateEvent в FormCreate?
2. GetLastError при отсутствии проверки возвращаемого значения WaitForMultipleObjects — нонсенс.
3. Остальных манипуляций, честно говоря, и касаться не хочу.


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо