Текущий архив: 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.51 MB
Время: 0.006 c