Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2003.06.16;
Скачать: [xml.tar.bz2];

Вниз

Обработка исключений в 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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.51 MB
Время: 0.063 c
1-50362
Pesh
2003-06-04 00:33
2003.06.16
Как отследить появление чужого окна?


1-50397
Sergey26
2003-06-04 13:21
2003.06.16
Мастера, подскажите, как реализовано следующее:


6-50418
Beerlover
2003-04-13 20:37
2003.06.16
UDP socket


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


14-50454
snake1977
2003-05-29 17:26
2003.06.16
Захват таблицы





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский