Форум: "Основная";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2002.02.11;
Скачать: [xml.tar.bz2];




Вниз

Обработка исключительных ситуаций 


Abajun   (2002-01-28 13:39) [0]

Привет всем! В программе иногда возникает такая ситуация: вызывается функция из DLL и в ней программа прекращает работу, т.е. вылетает безо всяких ошибок. А мне нужно, чтобы если она вылетает и функция до конца не отработает, то все равно дальше продолжать работу программы. Не подскажите, как правильнее всего это сделать?



Андрей Сенченко   (2002-01-28 13:43) [1]

try .. except
или
try .. finally

Судя по вопросу, скорее второе



Abajun   (2002-01-28 13:55) [2]

Так это все и написано:

try
Lvpp:= SomeFunction(a1,...);
except
Lvpp:= 100000;
end;

Иногда SomeFunction вылетает и программа дальше не идет, а хотелось, чтобы работал блок except. Как я понимаю, такой общий вид работает на все виды исключительных ситуаций. Так получается, что мой случай - это не такая ситуация?



Андрей Сенченко   (2002-01-28 14:00) [3]

Попробуй все-таки Finally. Лично я except-ом стараюсь не пользоваться. То ли он не понимает, что произошла исключительная ситуация, то ли я чего не то пишу, но если написано в Finally- работает, а если в Except - никак.



Abajun   (2002-01-28 14:04) [4]

Мне finally не подходит, т.к. этот блок выполняется обязательно, независимо от того, произошла ли ошибка или нет. А мне нужно в переменную Lvpp передать значение SomeFunction, а если в той какая-либо ошибка (не считает, например) - то присвоить значение 100000. Если функция вылетает - для меня это тоже результат.



MBo   (2002-01-28 14:18) [5]

если не разбираться в причинах, то можно по-тупому


try
Flag:=True;
Lvpp:= SomeFunction(a1,...);
flag:=False;
except
if Flag then
Lvpp:= 100000;
end;



Abajun   (2002-01-28 14:29) [6]

В строчке
Lvpp:= SomeFunction(a1,...)
программа заканчивает работу и ни на какой
flag:=False;
не пойдет.



MBo   (2002-01-28 14:31) [7]


ошибся

try
Flag:=True;
Lvpp:= SomeFunction(a1,...);
flag:=False;
finally
if Flag then
Lvpp:= 100000;
end;



Digitman   (2002-01-28 14:33) [8]

какое исключение возникает при выполнении вызова DLL-ф-ции ?



Abajun   (2002-01-28 14:48) [9]

А я не знаю - она просто вылетает и все. Кроме того, она вызывается и начинает считать, но в процессе выполнения что-то там не срабатывает (какие-то математические ошибки) и все.



Digitman   (2002-01-28 15:04) [10]

DLL "чужая" (без исх.текстов) или твоей разработки ?



Abajun   (2002-01-28 15:19) [11]

Исходники есть, но на Fortran (присоединяется через LoadLibrary).
Можно считать, что DLL закрыта.



Digitman   (2002-01-28 15:26) [12]

Импортировал правильно ? с соблюдением соглашений о связях с Fortran-кодом ?



Abajun   (2002-01-28 15:41) [13]

Все правильно. При некоторых сочетаниях фактических параметров функция считает и выдает результат, а при некоторых этот счет невозможен. Вот в последнем случае мне и необходимо переменной присвоить определенное число. Только "невозможность счета" - это вылет из функции.



Digitman   (2002-01-28 15:48) [14]

приведи декларацию импортируемой ф-ции и фрагмент кода ее вызова с декларацией всех факт.параметров



Abajun   (2002-01-28 16:00) [15]



type
TSub1 = function(a1,a2,a3,a4,a5,a6 : real) : real; stdcall;

var
Handle: THandle;
F4 : TSub1;
boolF4 : boolean;
Totn,G,GS,RG,m,Piv : real;

begin
...
boolF4:= false;
Handle := LoadLibrary("FortDLL-9.dll");
if Handle <> 0 then begin
@F4 := GetProcAddress(Handle,"LVPP");
if @F4 <> nil then boolF4:= true;
end;

...

Totn:= ...; G:= ...; GS:= ...; RG:= ...; m:= ...; Piv:= ...;
if boolF4 = true then
try
Lvpp:= F4(G,GS,RG,m,Totn,Piv);
except
Lvpp:= 100000;
end
else Lvpp:= 100000;

...

end;



Digitman   (2002-01-28 16:19) [16]

т.е., ты хочешь сказать, что объявление
Totn,G,GS,RG,m,Piv : real;
не меняется, а меняется лишь
Totn:= ...; G:= ...; GS:= ...; RG:= ...; m:= ...; Piv:= ...;

и при некоторой комбинации происходит сбой ?
еще раз - уверен ли ты, что декларация ф-ции достоверна ? может, один из параметров должен передаваться не по значению, а по ссылке ?



Abajun   (2002-01-28 16:24) [17]

Да. При некоторой комбинации переменных функция не считает. В этом случае в Lvpp нужно записать определенное число. Все декларации правильные и проверенные. Тем более в большинстве случаев функция вызывается и считает (правильно считает - проверено), а некоторых нет (что тоже нормальная ситуация). Просто мне надо, чтобы она не вылетала в

Lvpp:= F4(G,GS,RG,m,Totn,Piv);

а дальше продолжала работать.



MBo   (2002-01-28 16:29) [18]

обычно в fortran параметры передаются по ссылке (var)
кроме того, настораживает real - Delphi какие?
в новых по умолчанию real=double, но надежнее так и писать double.
Хотя, раз иногда работает верно -(и результат правильный?), то дело, вероятно, не в этом



MBo   (2002-01-28 16:30) [19]

а, пока писал - все ответили



Digitman   (2002-01-28 16:41) [20]

трассировать работу ф-ции в окне CPU не пытался ?



Digitman   (2002-01-28 16:45) [21]

Кстати, да, действительно упущенный (и оч.важный) момент ! <MBo> верно подсказывает, что в Fortran-подпрограммы факт.параметры должны передаваться по ссылке. Это и наводит на мысль, что декларация ф-ции неверна



Abajun   (2002-01-28 16:52) [22]

Все правильно передается - проверено много раз (могу в некоторых пределах менять dll - вставляю печать в файл переданных параметров). Все правильно в отдельных случаях считает. А в некоторых оно и не должно считать - это тоже правильно (я могу рассказать о сути задачи, если это улучшит понимание). Просто эти случаи надо отловить, но как?
Насчет CPU-окна я ничего не знаю.



Digitman   (2002-01-28 17:18) [23]

Ну-у-у, полезли в дебри) ...
Ты оспариваешь то факт, что соглашения о передаче факт.параметров в Fortran-подпрограмму предписывают передачу параметров по ссылке ? Или ты утверждаешь, что твоя DLL - Fortran-compatible, хотя на самом деле это может быть и не так ?

"А в некоторых оно и не должно считать" - это как понять ? кто это - "оно" ?

"Насчет CPU-окна я ничего не знаю" - печально, что ж тут сказать( ...



Abajun   (2002-01-28 17:38) [24]

Я ничего не оспариваю. Я просто говорю, что никаких нарушений по передаче параметров нет. Кстати, я могу и ошибаться, но директива stdcall, по-моему, означает передачу параметров по значению.
Извините, "оно" - это просто так. В смысле программа.
Хотелось просто узнать, можно ли как-то отловить непредвиденный выход из программы.
Или я что-то не так спрашиваю?



Иван Шихалев   (2002-01-28 17:42) [25]

Насколько я помню, при возникновении исключительной ситуации в DLL, вызывающая ее программа просто слетает (причем, DLL остается в памяти). Так что, видимо, придется лезть в Fortran и прописывать там нормальный выход вместо исключения.



Abajun   (2002-01-28 17:49) [26]

2 Иван Шихалев
Правильно - слетает. Значит в Делфи нельзя никак реализовать, чтобы не слетала?



Digitman   (2002-01-28 17:56) [27]

Директива stdcall отнюдь не означает способ передачи параметров, а означает она порядок их помещения в стек и указание Pascal-компилятору о том, что за баланс стека после завершения вызова ответственен сам вызываемый код. Вот и все. Но, кр.того, Fortran-п/программа ожидает, что переданные ей через стек в кач-ве факт.параметров величины являются не самими значениями, а указателями на адреса памяти, где эти значения хранятся.
Что делает ф-ция и что должна возвращать ?
Назначение параметров ?
Пример кода, когда передав ф-ции конкретные, определенные тобой и допустимые параметры, ты все же получил рез-т ее работы, соответствующий ожидаемому по описанию ф-ции ? Проверена ли правильность рез-та иными средствами (сказем, расчетами на обычном калькуляторе, если это возможно) ?



Abajun   (2002-01-28 18:10) [28]

2 Digitman
Почему тогда в хелпе по Фортрану написано, что

Calling Conventions for ATTRIBUTES Options

Default C STDCALL C,REFERENCE STDCALL,REFERENCE
Scalar Reference Value Value Reference Reference

Ну может, я что-то упустила.
Далее. Функция выполняет математические расчеты движения самолета и возвращает некоторое число - длину взлетно-посадочной полосы самолета. Параметры - это некоторые геометрические харак-ки самолета.
Перед вызовом функции им присваиваются определенные значения, например:
Totn:= 0,96; G:= 69,7; GS:= 570; RG:= 0,26; m:= 12,0; Piv:= 1,4;
В этом случае Lvpp = 3013,97.
При другом сочетании самолет просто не может полететь. Поэтому и функция не считает. Матмодель - не моя, редактировать ее мне сложно. Проверка осуществлялась на exe-шнике, из которого потом и переделывалась DLL.



Digitman   (2002-01-28 18:30) [29]

Функция НЕ МОЖЕТ НЕ СЧИТАТЬ ! В любом случае она обязана вернуть какой-либо результат, и , если вместо этого происходит непредусмотренный сбой в работе вызвающего ее кода, это говорит только об одном (при условии, что код вызываемой ф-ции отлажен) - неверно интерпретируются вх.параметры (если они есть) или неверно передается вых.результат.
Ну, я уж не знаю, что там может "не полететь" или "полететь не так, как хотелось бы", но - это факт.
Приведи тогда полный Паскаль-прототип библиотечных типов, где декларируется все, что экспортируется библиотекой. В том виде, как он тебе попал в руки (именно - источник первоначальной инф-ции об интерфейсе DLL), а не отредактированный уже тобой в процессе экспериментов. Будем сравнивать и анализировать.
В кр.случае, присылай саму DLL и всю док-цию, какой она сопровождается.



Abajun   (2002-01-28 18:42) [30]

Так в том и дело, что код не отлажен (как мне кажется). Тот кто писал саму программу на Fortrane, считает, что раз выдается ошибка (скорей всего математическая - деление на ноль и т.д.), программа вылетает - то значит этот случай неправильный. Меняются исходные данные - и все по новой. А у меня теперь из нее сделана DLL. Только такой вылет меня не устраивает. Так как на Делфи для меня было проще, то я решила обработать такую ситуацию здесь. Но теперь понимаю, что это практически невозможно, необходимо лезть в Фортран и там исправлять или матмодель (отлаживать), или обрабатывать исключения в DLL на Фортран.
Ладненько, спасибо большое за советы.



VictorT   (2002-01-29 10:31) [31]

Недавно сам столкнулся с подобной проблемой. Грабли оказались в том, что запускал програму из Дельфей (Run), а Дельфи отслеживает все исключительные ситуации (даже те, которые нормально обрабатываются), и прерывают програму с сообщением об этом, для продолжения роботы нужно нажать Run. Чтобы робота програмы не прерывалась, нужно её откомпилить и запускать полученый ЕХЕ-шник. Возможно, твоя проблема в этом.




Форум: "Основная";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2002.02.11;
Скачать: [xml.tar.bz2];




Наверх





Память: 0.79 MB
Время: 0.027 c
1-32208           Вовчик                2002-01-25 21:43  2002.02.11  
Ошибка в вычислениях


1-32274           чайничек              2002-01-27 09:50  2002.02.11  
Переместить название одного узла (подузла) TTreeView в Edit или ComboBox


6-32311           Gunner                2001-11-17 00:21  2002.02.11  
Point to Point Protocol


1-32259           Лана Розанова         2002-01-28 13:17  2002.02.11  
KeyPress


14-32342          Sour                  2001-12-22 09:11  2002.02.11  
Помогите установить компоненты.