Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2003.06.16;
Скачать: CL | DM;

Вниз

Обработка исключений в DLL   Найти похожие ветки 

 
Петр ©   (2003-06-03 13:06) [0]

Добрый день, уважаемые знатоки !

Есть такая проблема:

Имею DLL, в которой есть функция CoderFile(FileName, CryptFileName : PChar) : Integer; , где обрабатываются файлы. В данной функции, я обрабатываю исключения, на случай, если возникнет какая-либо ошибка при работе с файлами (файл не доступен, неправильное имя и.т.д). При возникновении исключительной ситуации возвращаю код ошибки.
Все вроде-бы ничего.

Решил проверить работоспособность обработки. Создаю условия для ее возникновения.

В главной программе, при вызове данной функции, у меня возникает исключительная ситуация, но вся проблема в том, что код ошибки возвращается неправильно. Он остается на прежнем значении, т.е. Исключительную ситуацию я обработал в DLL, а затем, при вызове функции опять возникает: (НО МНЕ ЭТОГО НЕ НУЖНО, МНЕ НУЖНО, ЧТОБЫ ВОЗВРАТИЛСЯ ТОЛЬКО КОД ОШИБКИ).


Везде и в DLL и в программе, откуда идет вызов, я использую конструкции try..except.

Даже пробовал использовать директиву safecall вместо stdcall.
Может я неправильно работаю с директивой safecall. Пришлите пример, если у кого есть.

Может кто сталкивался с подобными проблемами?

С уважением,
Петр.


 
Skier ©   (2003-06-03 13:11) [1]

1)safecall здесь совсем не нужно вполне хватит и stdcall.
(safecall это тот же самый stdcall только в try-except-блоке)
2)Покажи как вызываешь DLL - функцию и как она объявлена в
host-приложении


 
Петр ©   (2003-06-03 13:16) [2]

Объявляю функцию в приложении:

...

Var
Form1 : TForm;


function fCoderGost(Key,FileName,CryptFileName : PChar): Integer; stdcall;
function fDeCoderGost(Key,CryptFileName,FileName : PChar): Integer; stdcall;

implementation

function fCoderGost(Key,FileName,CryptFileName : PChar): Integer; external "GostLib.dll" name "fCoderGost";
function fDeCoderGost(Key,CryptFileName,FileName : PChar) : Integer; external "GostLib.dll" name "fDeCoderGost";


Вызываю функцию по обработчику нажатия на Button

procedure TForm1.Button1Click(Sender: TObject);
Var
_R : Integer;

Begin
Key:="R9JNPBGNHW2S8PZ4SDLLKJ4TNYR5M4N9";
Try
_R:=fCoderGost(Key,"1.txt","1.gst");
Except
ShowMessage(IntToStr(_R));
End;
End;


 
Skier ©   (2003-06-03 13:27) [3]

Не поможет ?

Var
Form1 : TForm;


function fCoderGost(Key,FileName,CryptFileName : PChar): Integer; stdcall;external "GostLib.dll" name "fCoderGost";
function fDeCoderGost(Key,CryptFileName,FileName : PChar) : Integer; stdcall; external "GostLib.dll" name "fDeCoderGost";

implementation

Вызываю функцию по обработчику нажатия на Button

procedure TForm1.Button1Click(Sender: TObject);
Var
_R : Integer;

Begin
Key:="R9JNPBGNHW2S8PZ4SDLLKJ4TNYR5M4N9";
_R:=fCoderGost(PChar(Key),PChar("1.txt"),PChar("1.gst"));
ShowMessage(IntToStr(_R));
End;


 
Петр ©   (2003-06-03 13:38) [4]

Пробовал, результат тот же...


 
Skier ©   (2003-06-03 13:39) [5]


> При возникновении исключительной ситуации возвращаю код
> ошибки.

Как возвращаешь ?


 
Петр ©   (2003-06-03 13:48) [6]

Имею в DLL такую функцию:

library GostLib;


Uses
SysUtils,Windows,GOST;

function fCoderGost(Key,FileName,CryptFileName : PChar): Integer; stdcall;
Begin
Result:=CoderFile(Key,FileName,CryptFileName);
End; { fCoderGost }

Exports
CoderGost;


А в модуле GOST - функцию CoderFile

Возвращаю код ошибки так:

...
...

KeyBin:=KeyToBit(GOST.Key);
Try
AssignFile(FText,_FileName);
Reset(FText,1);
Except
on E: EInOutError do
Begin
Case E.ErrorCode of
2: CodeError:=12;
3: CodeError:=13;
4: CodeError:=14;
5: CodeError:=15;
100: CodeError:=1100;
101: CodeError:=1101;
106: CodeError:=1106;
End; { Case E.ErrorCode }

CloseFile(FText);
Result:=CodeError;
Exit;
End; {E: EInOutError }
End;

{ Если ошибки нет, то продолжаем... }
SizeFile:=FileSize(FText);


 
Skier ©   (2003-06-03 14:02) [7]

А если сделать так (временно), будет правильно давать 0 или 1 ?

Result := 0;
KeyBin:=KeyToBit(GOST.Key);
Try
AssignFile(FText,_FileName);
Reset(FText,1);
Except
Result := 1;
CloseFile(FText);
end; //try


 
Петр ©   (2003-06-03 14:23) [8]

ВЫДАЛА 1.

И еще одна странность: Прогоняю дебаггером главную программу - исключение выдает. А если запустить EXE, то не выдает никаких исключений. Странно.

Мне тоже не понятно, почему при возникновении ошибок ввода-вывода, машина не понимает EInOutError, по сути, я его убрал...


 
Skier ©   (2003-06-03 14:31) [9]

Проверь директиву {$I+/-}

> Прогоняю дебаггером главную программу - исключение выдает.
> А если запустить EXE, то не выдает никаких исключений. Странно.

Ошибка, вестимо...


 
Петр ©   (2003-06-03 14:38) [10]

Если честно, то я с директивами вообще не работал, но кое-что читал про них.

в самом верху модуля у меня такие строки:

{$A+,B-,C+,D+,E-,F-,G+,H+,I+,J+,K-,L+,M-,N+,O+,P+,Q-,R-,S-,T-,U-,V+,W-,X+,Y+,Z1}
{$MINSTACKSIZE $00004000}
{$MAXSTACKSIZE $00100000}
{$IMAGEBASE $00400000}
{$APPTYPE GUI}

Стояло I+, поменял на I- (перекомпелировал), тот же результат, исключения нет, хотя в дебагере прогоняешь - есть.

Может в Delphi глюк или в моих мозгах?


 
rkostya   (2003-06-03 14:48) [11]

По порядку:

KeyBin:=KeyToBit(GOST.Key);
Try
AssignFile(FText,_FileName);
Reset(FText,1);
Except
on E: EInOutError do
Begin
Case E.ErrorCode of
2: CodeError:=12;
3: CodeError:=13;
4: CodeError:=14;
5: CodeError:=15;
100: CodeError:=1100;
101: CodeError:=1101;
106: CodeError:=1106;
End; { Case E.ErrorCode }

CloseFile(FText);
Result:=CodeError;
Exit;
End; {E: EInOutError }
End;

Во-первых, если у тебя при открытии файла произошла ошибка, то файл не открыт, и CloseFile приводит к появлению exception-а в обработчике исключений
Во-вторых, убери Exit из обработчика исключений. Ты разрываешь обработчик, поэтому обьект исключения не будет уничтожен.

Едем дальше

Try
_R:=fCoderGost(Key,"1.txt","1.gst");
Except
ShowMessage(IntToStr(_R));
End;

Конструкция бессмысленная. Ты никогда не увидишь кода ошибки. Переменной _R что-то присвоится только в случае успешного завершения fCoderGost, но в этом случае не будет вызвана ShowMessage(IntToStr(_R)). При возникновении исключения переменной _R ничего не будет присвоено, и ее значение останется таким же, как и до начала блока Try.


 
Петр ©   (2003-06-03 15:02) [12]

>rkostya
Насчет Exit - это верно, может его убрать вот сюда?

Try
AssignFile(FText,_FileName);
Reset(FText,1);
Except
on E: EInOutError do
Begin
Case E.ErrorCode of
2: CodeError:=12;
3: CodeError:=13;
4: CodeError:=14;
5: CodeError:=15;
100: CodeError:=1100;
101: CodeError:=1101;
106: CodeError:=1106;
End; { Case E.ErrorCode }

Result:=CodeError;
End; {E: EInOutError }
Exit;
End;


Попробую сделать с учетом Ваших комментариев. Спасибо большое Всем участникам дискуссии.


 
Петр ©   (2003-06-03 15:10) [13]

Есть ли ф Delphi функция, которая проверяет состояние файла открыт он или нет?


 
VMcL ©   (2003-06-03 17:10) [14]

>Петр © (03.06.03 15:10)

File - это по большому счёту TFileRec. См. TFileRec.


 
М   (2003-06-03 17:12) [15]

>Петр © (03.06.03 15:10)

Можно написать так (небольшой изврат):
try
// ...
except
//...
try
CloseFile(FText);
except
end;
end;


 
VMcL ©   (2003-06-03 17:12) [16]

>Петр © (03.06.03 15:10)

Можно написать так (небольшой изврат):
try
// ...
except
//...
try
CloseFile(FText);
except
end;
end;


 
VMcL ©   (2003-06-03 17:13) [17]

Sorry за >М (03.06.03 17:12)<, проглючило...


 
Morfein ©   (2003-06-03 19:04) [18]

Чтобы всё работало, не надо использовать дебильные методы AssignFile и иже с ними... Windows предоставляет функции для работы с файлами, которые не генерируют исключений и для которых легко получается код ошибки, если она произошла:

f:=CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
if f = INVALID_HANDLE_VALUE then
begin
Result:=GetLastError();
exit;
end;
ReadFile(f, ...);
WriteFile(f, ...);
CloseHandle(f, ...);


Всё! Никаких Try...Except и прочих ненужных конструкций!
Подробности в Win32 Programmer"s Reference, раздел Files


 
rkostya   (2003-06-04 14:36) [19]

2 Петр © (03.06.03 14:23)
ВЫДАЛА 1.
И еще одна странность: Прогоняю дебаггером главную программу - исключение выдает. А если запустить EXE, то не выдает никаких исключений. Странно.

Выдала 1 потому, что присвоение Result:=1 стоит _до_ CloseFile.
А странности никакой нет. Просто программа исключение обрабатывает в блоке except, а дебагер перехватывает и отображает _все_ исключения, даже те, которые программа обрабатывает. Точнее, это указывается в настройках, но по умолчанию дебагер ведет себя именно так.

А насчет Exit я погорячился - Делфи (по крайней мере 6-й) коррктно обрабатывает Exit в блоке обработки исключений. :) Хотя на вашем месте я бы его вообще выбросил, и между try ... except поместил все тело функции. Тогда _все_ ошибки (а не только открытия файла) можно обработать в одном блоке. Что намного эффективнее, чем анализировать коды возврата после каждого вызова функций чтения\записи или выделения памяти или... (список можно продолжать долго), как отрометчиво советует делать Morfein :)

Теперь о том, как и когда закрывать файл. Вообще, для освобождения выделенных ресурсов (закрытие файлов, освобождения памяти) существует конструкция try ... finally. Т.е. функция в общем случае должна выглядеть примерно так

try
try
GetMem(p,BUF_SIZE);
AssignFile(f,FILE_NAME);
Reset(f,REC_SIZE);
...
BlockRead(f,...);
...
except
...
end;
finally
...
if Assigned(p) then
begin
FreeMem(p);
p:=nil;
end;
{$I-} // Отключить генерацию исключений EInOutError
CloseFile(f);
IOResult; // Сбросить флаг ошибки
{$I+} // Включить исключения
...
end;



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

Текущий архив: 2003.06.16;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.015 c
1-50338
vlv
2003-06-03 15:12
2003.06.16
Как вычислить разность двух TDateTime в минутах?


14-50519
Soft
2003-05-29 12:28
2003.06.16
Солгласны ли вы обменять свободу на материальные блага?


1-50302
кто-то
2003-06-04 18:17
2003.06.16
Как встроить ActiveX в HTML?


14-50477
Alekss S.
2003-05-28 16:51
2003.06.16
DBD, запуск с параметрами


14-50497
Школьник
2003-05-28 14:55
2003.06.16
Где можно скачать MSDN, SDK и прочие справочные системы?