![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
WaitForMultipleObject, Event, ReadDirectoryChangesW, AV
Анонимщик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. Остальных манипуляций, честно говоря, и касаться не хочу.