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

Вниз

try..except   Найти похожие ветки 

 
Hit   (2005-10-18 13:19) [0]

Мастера, помогите.
Пишу код и решил заюзать raise вместо возвращения кода ошибки из функции. Все шло нормально, но потом на одной из процедур после raise, я вижу свое сообщение(отлаживаюсьс IDE), но дальше какой-то мусор вместо перехода в верхний обработчик ошибок:
Project test.exe faulted with message: "application-defined exception (code 0x0eedfade) at 0x77e73887". Process Stopped. Use Step or Run to continue.
Куда рыть?


 
han_malign ©   (2005-10-18 13:26) [1]

Tool->Debugger Options->Language Exceptions
- вот туда и рой...

З.Ы. А вот насчет исключения из DLL("at 0x77e73887") - не уверен, что все так гладко и просто...


 
Leonid Troyanovsky ©   (2005-10-18 13:50) [2]


> Hit   (18.10.05 13:19)  

> Куда рыть?


Прежде всего, показать откуда оный raize вызывается,
(консоль, thread, etc), его код. И что есть "верхний обработчик".

--
Regards, LVT.


 
Hit   (2005-10-18 14:36) [3]


> Прежде всего, показать откуда оный raize вызывается,
> (консоль, thread, etc), его код. И что есть "верхний обработчик".

Есть поток, который в методе Synchronize дергает методы из других юнитов.
Так вот, один такой метод(в котором трабл) выглядит так(упрощенно):

procedure TMyClass.DoSomething();
begin
 try
   DoSomething1();
   DoSomething2(); // после того как тут срабатывает raise, почему-то обработчик не уходит в блок except, а идет к методу DoSomething3
   DoSomething3();
 except
   rasie; // re-raising для передачи в поток
 end;
end;

procedure TMyClass.DoSomething1();
begin
  if IsTrue() then
 begin
   ...
 end else
 begin
    raise Exception.Create("Error in DoSomething1");
 end;
end;

procedure TMyClass.DoSomething2();
begin
 //тут работаю с БД
  if IsTrue() then
 begin
   ...
 end else
 begin
    raise Exception.Create("Error in DoSomething2");
 end;
end;

DoSomething3 не привожу, так как до него не доходит.


 
Hit   (2005-10-18 15:12) [4]

И еще, еси запускать без делфи, то прога ничего не выдает - уходит в небытие....


 
Hit   (2005-10-18 15:18) [5]

Народ ау...


 
evvcom ©   (2005-10-18 15:24) [6]

На [1] ты не обратил внимания? По каким адресам размещается твоя программа? Почему исключение at 0x77e73887, т.е. по такому адресу?


 
Hit   (2005-10-18 15:29) [7]

Та нету у меня длл.... поэтому и не обратил.
В настройках делфи галочки стоят у:
Delphi EAbort Exceptions
Microsoft DAO Exceptions
VisiBroker Internal Exceptions
CORBA System Exceptions
и у Stop on Delphi Exceptions


 
evvcom ©   (2005-10-18 15:40) [8]


> Та нету у меня длл.... поэтому и не обратил.

Это как же это ты без kernel32, user32, gdi32 dll работаешь? Без единой библиотеки! Ну ка расскажи-ка нам...


 
Leonid Troyanovsky ©   (2005-10-18 15:46) [9]


> Hit   (18.10.05 14:36) [3]

> Есть поток, который в методе Synchronize дергает методы
> из других юнитов.
> Так вот, один такой метод(в котором трабл) выглядит так(упрощенно):



Приведенное содержит даже синтаксические ошибки,
чего ты предлагаешь разбирать?

Приводить принято минимально достаточный код, гарантированно
воспроизводящий проблему. Кроме того, если ты уважаешь
отвечающих, код должен компилироваться.

Зачем нам знать про какие-то IsTrue, DoSomething1, DoSomething3 и др.,
что к делу не относится.
Как, собс-но, и комментарий, иллюстрирующий незнание RTFM.

Ну, а код который мог бы прояснить проблему опущен.

--
Regards, LVT.


 
Leonid Troyanovsky ©   (2005-10-18 15:50) [10]


> Hit   (18.10.05 15:12) [4]
> И еще, еси запускать без делфи, то прога ничего не выдает
> - уходит в небытие....


Хе-хе. С этого б и начал.
Необработанное исключение во вторичном потоке.

RTFM, RTFM, RTFM
Ссылочку на туториалы я вчерась кидал.

--
Regards, LVT.

PS Т.е., все, что ты рассказывал о своем коде - туфта.


 
han_malign ©   (2005-10-18 15:50) [11]


> Есть поток, который в методе Synchronize дергает методы
> из других юнитов.


> Почему исключение at 0x77e73887, т.е. по такому адресу?

- а потому, что в Synchronize - исключение срабатывает внутри очереди сообщений(в контексте основного потока, в недрах одной из kernel32, user32, gdi32), и ничего хорошего из этого получиться не может... При чем есть подозрение, что основной поток после этого прекращает существование...


 
Hit   (2005-10-18 15:56) [12]


> [9] Leonid Troyanovsky ©   (18.10.05 15:46)

Виноват, исправлюсь.


> RTFM, RTFM, RTFM
> Ссылочку на туториалы я вчерась кидал.

Можно еще раз. плиз.


> Необработанное исключение во вторичном потоке.

Это каК?


 
е1   (2005-10-18 16:01) [13]


> han_malign ©   (18.10.05 15:50) [11]


Прекрасно поднимается исключение в доп. поток

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls;

type
 TForm1 = class(TForm)
   Button1: TButton;
   procedure Button1Click(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

procedure Test1;
procedure Test2;
procedure Test3;

implementation

uses Unit2;

{$R *.dfm}

procedure Test1;
begin
end;

procedure Test2;
begin
 raise Exception.Create("Raise test2");
end;

procedure Test3;
begin
 raise Exception.Create("Raise test3");
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 t: TTest;
begin
 t := TTest.Create(False);
end;

end.

------------------------------
unit Unit2;

interface

uses
 Classes,windows,SysUtils;

type
 TTest = class(TThread)
 private
   { Private declarations }
   procedure doSync;
 protected
   procedure Execute; override;
 end;

implementation

uses
 Unit1;

{ TTest }

procedure TTest.doSync;
begin
 try
   Unit1.Test1;
   Unit1.Test2;
   Unit1.Test3;
 except
   raise;
 end;

end;

procedure TTest.Execute;
begin
 FreeOnTerminate := True;
 try
   Synchronize(DoSync);
 except
   on E: Exception do MessageBox(0,PChar(E.Message),"Err",MB_OK);
 end;
end;

end.


 
Leonid Troyanovsky ©   (2005-10-18 16:05) [14]


> Hit   (18.10.05 15:56) [12]


Tutorial on thread programming in Delphi:

http://www.pergolesi.demon.co.uk/prog/threads/ToC.html
http://www.sklobovsky.com/community/threadmare/threadmare.htm

Handling exceptions in a thread:
http://community.borland.com/article/0,1410,10452,00.html


> > Необработанное исключение во вторичном потоке.
>
> Это каК?


RTL дельфи не обрабатывает исключения во вторичных потоках.
А Windows снимает процессы, в которых возникли необработанные
исключения.

--
Regards, LVT.


 
Leonid Troyanovsky ©   (2005-10-18 16:13) [15]


> 1   (18.10.05 16:01) [13]


> try
>   Synchronize(DoSync);
> except
>   on E: Exception do MessageBox(0,PChar(E.Message),"Err",MB_OK);
> end;

Не надо так делать.
Показ исключений в потоке нужно синхронизировать.
http://groups.google.com/group/fido7.su.windows.prog/msg/b5bdc95319027a8a

--
Regards, LVT.


 
е1   (2005-10-18 16:16) [16]


> Leonid Troyanovsky ©   (18.10.05 16:13) [15]


Это пример для демонстрации.


 
evvcom ©   (2005-10-18 16:54) [17]


> Это пример для демонстрации

Это неправильный пример, а посему его вредно демонстрировать.


 
Anatoly Podgoretsky ©   (2005-10-18 17:05) [18]

procedure TMyClass.DoSomething();
begin
// try
  DoSomething1();
  DoSomething2(); // после того как тут срабатывает raise, почему-то обработчик не уходит в блок except, а идет к методу DoSomething3
  DoSomething3();
// except
//   rasie; // re-raising для передачи в поток
// end;
end;


 
е1   (2005-10-18 18:08) [19]


> evvcom ©   (18.10.05 16:54) [17]
>
>
> > Это пример для демонстрации
>
> Это неправильный пример, а посему его вредно демонстрировать.
>


Можно чуть больше умных слов добавить, чтобы было более аргументированно, а не звучало как "трындеж"?


 
Leonid Troyanovsky ©   (2005-10-19 10:14) [20]


> е1   (18.10.05 18:08) [19]

> Можно чуть больше умных слов добавить, чтобы было более
> аргументированно, а не


Прежде всего, д.б. MessageBox(Application.Handle, ..).
Но, и это может быть небезопасно, бо следует помнить, что формы
и бокс, все же, в разных потоках, и что произойдет при обработке
некоего сообщения (например, таймера) в первичном потоке
предсказать  непросто.
Поэтому, при обработке исключений во вторичных потоках также
лучше придерживаться общего правила:
если нужно чего-то показывать, то поручим сделать это первичному
потоку путем Synchronize.

--
Regards, LVT.


 
Hit   (2005-10-19 16:23) [21]

Спасибо  Leonid Troyanovsky  за линки :)
Локализовал проблему. Проблема не в потоках и ексепшинах...
Проблема в функции, которая работает в DoSomething1, она на входе получает пять строковых параметров и интежер, и выдает строку. Алгоритм приветси не могу, так как у меня есть только *.dcu, т.е. есть но менять нет прав.
Функция работает, чего-то там делает(xor и всякие там операции с символами - короче шифрует строку). Выдает результат. После того как я генерю ексепшн, вылетает
Project test.exe faulted with message: "application-defined exception (code 0x0eedfade) at 0x77e73887". Process Stopped. Use Step or Run to continue. И показывается стек - видно, что kernel32.
Наверное где-то торочит память... Как можно не меняя эту функцию, защититься от нее?


 
Hit   (2005-10-19 16:40) [22]

Самое интересное, что эта функция работает уже полгода и небыло нареканий... Переписать ее не получится.
Что можно сделать?


 
Hit   (2005-10-19 17:15) [23]

Народ, помогите... плиз. Хоть утеште :)


 
umbra ©   (2005-10-19 17:20) [24]

ну хоть DoSomething1 то посмотреть можно?


 
е1   (2005-10-19 17:40) [25]


> Прежде всего, д.б. MessageBox(Application.Handle, ..).
> Но, и это может быть небезопасно, бо следует помнить, что
> формы
> и бокс, все же, в разных потоках, и что произойдет при обработке
>
> некоего сообщения (например, таймера) в первичном потоке
>
> предсказать  непросто.


1. Ошибаешься.  Application.Handle как раз не надо указывать - здесь я создаю немодальный диалог.
2. Формы и бокс в разных потоках и ничто не мешает им иметь свои обработчики сообщений, что в данном случае и наблюдается.

Поэтому здесь коррректный и безопасный код.


 
Hit   (2005-10-19 17:49) [26]


> ну хоть DoSomething1 то посмотреть можно?

Сорри, DoSomething2. Там код простой:

procedure TMyClass.DoSomething2();
var
 LoacalVar1: String;
begin
//тут работаю с БД, читаю из БД LoacalVar1
...
if (LocalVar1 = UnitCrypt.Crypt(Param1, Param2, Param3))then
begin
  ...
end else
begin
   raise Exception.Create("Error in DoSomething2");
end;
end;

procedure Crypt(Param1, Param2, Param3: String)
 function DoCryptItem(S1, S2: String): String;
 begin
   //xor-ы
    ...
 end;
begin
 Result := DoCryptItem(Result,Param1);
 Result := DoCryptItem(Result,Param2);
 Result := DoCryptItem(Result,Param3);
end;

Коментарю строку с if (LocalVar1 = UnitCrypt.Crypt(Param1, Param2, Param3))then все корректно работает.


 
Hit   (2005-10-19 17:51) [27]


> procedure Crypt(Param1, Param2, Param3: String)

сорри
function Crypt(Param1, Param2, Param3: String): String;


 
е1   (2005-10-19 18:02) [28]


> Коментарю строку с if (LocalVar1 = UnitCrypt.Crypt(Param1,
>  Param2, Param3))then все корректно работает.


А ты не комментируй, а защити блоком try..except и проверь, что за ошибка возникает.


 
Hit   (2005-10-19 18:05) [29]


> А ты не комментируй, а защити блоком try..except и проверь,
> что за ошибка возникает.

так блин нету ж ошибки, вот в чем зараза... Функция UnitCrypt.Crypt еще раз говорю - работает... Это я генерю сам ексепшн, вместо того, чтобы вернуть фолсе...


 
umbra ©   (2005-10-19 18:08) [30]


> procedure Crypt(Param1, Param2, Param3: String)
>{.........................}
> Result := DoCryptItem(Result,Param1);


А какой в процедуре может быть Result?


 
Hit   (2005-10-19 18:14) [31]

я ошибся...[27]


 
umbra ©   (2005-10-19 19:21) [32]

А если попробовать такую процедуру, то какое сообщение вылетает?


procedure TMyClass.DoSomething2();
var
LoacalVar1, crypted: String;
begin
try
 //тут работаю с БД, читаю из БД LoacalVar1
 ...
except
 ShowMessage("Database");
end;

try
 crypted := UnitCrypt.Crypt(Param1, Param2, Param3)
except
 ShowMessage("Crypt");

if (LocalVar1 = crypted)then
try

 ...
except
ShowMessage("Stuff");
end
else
begin
  raise Exception.Create("Error in DoSomething2");
end;
end;


 
Leonid Troyanovsky ©   (2005-10-20 09:08) [33]


> Hit   (19.10.05 16:23) [21]

> Локализовал проблему. Проблема не в потоках и ексепшинах.
> ..


Неточно локализовал.
Exception code 0x0eedfade - означает, что это исключение Windows,
сгенерированное RTL дельфи.
В первичном потоке подобные исключения проявились бы как привычные
Exception. Ну, а во вторичных потоках таких механизмов нет.
Ну, и kernel32 здесь особо ни причем.

--
Regards. LVT.


 
Leonid Troyanovsky ©   (2005-10-20 09:14) [34]


> е1   (19.10.05 17:40) [25]

> Поэтому здесь коррректный и безопасный код.


Ходящие по граблям не должны на обижаться на то,
что я промолчал.

--
Regards, LVT.


 
Игорь Шевченко ©   (2005-10-20 10:12) [35]


> Пишу код и решил заюзать raise вместо возвращения кода ошибки
> из функции


А может, ларчик проще открыть ? Возвращать код ошибки и не мучиться ?


 
Hit   (2005-10-20 10:54) [36]


> А может, ларчик проще открыть ? Возвращать код ошибки и
> не мучиться ?

Нет, там вся концепция на ексепшинах...
в общем набрался смелости и подправил функцию криптографии, там писали в строку ограниченной длинны без проверки границ... В общем добавил пару условий - и о чудо пошло!
Всем спасибо.


 
е1   (2005-10-20 13:09) [37]


> Leonid Troyanovsky ©   (20.10.05 09:14) [34]
>
>
> > е1   (19.10.05 17:40) [25]
>
> > Поэтому здесь коррректный и безопасный код.
>
>
> Ходящие по граблям не должны на обижаться на то,
> что я промолчал.


Совершенно верно.
И не только промолчал, но и не привел никаких аргументов в пользу своей точки зрения, т.е. - потрындел немного.


 
е1   (2005-10-20 13:11) [38]


> Leonid Troyanovsky ©   (20.10.05 09:14) [34]


Кроме того, повторю еще раз - код для примера, одноразовый. Единственно для того, чтобы показать, что Exception успешно передается на верхний уровень.


 
Игорь Шевченко ©   (2005-10-20 13:33) [39]

Hit   (18.10.05 14:36) [3]


> Есть поток, который в методе Synchronize дергает методы
> из других юнитов.
> Так вот, один такой метод(в котором трабл) выглядит так(упрощенно):
>


А нафига вообще в методе потока делать работу в Synchronize в твоем конкретном случае ?

В чем тогда смысл потока и возни с Exceptions ?
Synchronize же выполняет код в основном потоке, я, честно говоря, не вижу особой пользы от такого распараллеливания...


 
Leonid Troyanovsky ©   (2005-10-20 13:44) [40]


> е1   (20.10.05 13:09) [37]

> И не только промолчал, но и не привел никаких аргументов
> в пользу своей точки зрения, т.е. - потрындел немного.


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

--
Regards, LVT.


 
Hit   (2005-10-20 14:17) [41]


> [39] Игорь Шевченко ©   (20.10.05 13:33)

Поток мне нужен для подключения к БД. Когда недоступен сервер и т.п. ошибок(прога замирает на таймаут) мне нужно, что-бы главная форма появилась и туда в лог(Мемо) пошли сообщения : об ошибках, об этапах работы алгоритмов...


 
е1   (2005-10-20 14:42) [42]


> Leonid Troyanovsky ©   (20.10.05 13:44) [40]
>
> Во-первых, свою точку зрения я обосновал
> (есть контраргументы - выслушаю).
> Во-вторых, я не провоцировал хамства
> (есть что-то личное - мой адрес в данных).
>
> --
> Regards, LVT.


Еще раз.
MessageBox вызывается без хендла родительского окна - в немодальном режиме. неважгНО. в каком потоке будет создаваться экно диалога.

Где-то здесь грабли? Если здесь, то в чем?

Код, приведенный в е1, совершенно рабочий, создан для демонстрации передачи исключения наверх.

Здесь грабли?

А так как в Leonid Troyanovsky ©   (20.10.05 09:14) [34] совершенно безосновательно написано в мой адрес

> Ходящие по граблям не должны на обижаться на то,
> что я промолчал.


лишь демонстрирует, что высказывание е1   (20.10.05 13:09) [37] о трындеже  совершенно верно зарактеризует положение.

Не надо провозглашать истины без достаточных на то аргументов, даже если на фуражке голубая бляха.


 
Игорь Шевченко ©   (2005-10-20 15:22) [43]

Hit   (20.10.05 14:17) [41]


> Поток мне нужен для подключения к БД.


Насколько я понял твой пост [3], подключение ты тоже выполняешь внутри Syncronize, в этом случае, как главная форма сможет отображать ход и ошибки подключения ?

Может быть, ты приведешь более полный код, чтобы можно было подсказать некое решение ?


 
Hit   (2005-10-20 15:40) [44]


> Насколько я понял твой пост [3], подключение ты тоже выполняешь
> внутри Syncronize, в этом случае, как главная форма сможет
> отображать ход и ошибки подключения ?

у нее есть паблик функция, которой я передаю текст.
А остальные классы: датамодуль(коннект к базе), алгоритмы выдают или текст ошибки(я сам raise-ю или ексепшины) или пишу напрямую в палик функцию. Все работает в потоке через Syncronize, мож я конечно намутил. Буду рад советам.


 
Leonid Troyanovsky ©   (2005-10-20 15:59) [45]


> е1   (20.10.05 14:42) [42]

> MessageBox вызывается без хендла родительского окна - в
> немодальном режиме. неважгНО. в каком потоке будет создаваться
> экно диалога.


Исключение возбуждено, оно не обработано, т.к., не было выхода из except,
от юзера требуется реакция (показан MessageBox).
Но, первичный поток вполне может продолжать работу, т.к. модальный
диалог показан немодально.

Однако, даже если он был показан хоть трижды немодально, то это никак
не препятствует дальнейшему выполнению приложения уже в неконсистентном
состоянии (за счет необработанного исключения).

--
Regards, LVT.

ЗЫ  Свое обещание я выполнил, контраргументы выслушал, и  мой ответ
тому доказательство (хотя, это лишь рефрен).

Ну, и разрешите откланяться, достаточно уж.


 
Игорь Шевченко ©   (2005-10-20 16:12) [46]

Hit   (20.10.05 15:40) [44]


> Все работает в потоке через Syncronize, мож я конечно намутил.
>  Буду рад советам.


С этого момента желательно проиллюстрировать кодом. Хотя бы схематично, методы Execute, синхронизируемые методы.

Поток, он вообще-то нужен для параллельного выполнения чего-либо, а Synchronize, как следует из перевода, требуется для синхронного (в данном случае, с первичным потоком) выполнения кода. Поэтому мне и интересно, как выглядит тело потока(ов)


 
е1   (2005-10-20 17:15) [47]


> Leonid Troyanovsky ©   (20.10.05 15:59) [45]
>
>
> > е1   (20.10.05 14:42) [42]
>
> > MessageBox вызывается без хендла родительского окна -
> в
> > немодальном режиме. неважгНО. в каком потоке будет создаваться
>
> > экно диалога.
>
>
> Исключение возбуждено, оно не обработано, т.к., не было
> выхода из except,
> от юзера требуется реакция (показан MessageBox).
> Но, первичный поток вполне может продолжать работу, т.к.
>  модальный
> диалог показан немодально.
>
> Однако, даже если он был показан хоть трижды немодально,
>  то это никак
> не препятствует дальнейшему выполнению приложения уже в
> неконсистентном
> состоянии (за счет необработанного исключения).


Леонид, ну это же демагогия.

Автору надо было получить исключение в доп. потоке. пример иллюстрирует это.

Дальше уже дело автора, что с этим исключением делать.
Естественно, его надо обработать и погасить.
Либо не обработать и передать для обработки в основной поток.
Но это уже совсем другая история.

Кроме того, в примере это исключение как раз и обработано.
Поэтоу не вижу в примере "неконсистентного состояния" ни при каких обстоятельствах.

И аргументы просто высосаны из пальца.

Не так ли?


 
Игорь Шевченко ©   (2005-10-20 17:40) [48]

procedure TThread.Synchronize(Method: TThreadMethod);
begin
 FSynchronizeException := nil;
 FMethod := Method;
 SendMessage(ThreadWindow, CM_EXECPROC, 0, Longint(Self));
 if Assigned(FSynchronizeException) then raise FSynchronizeException;
end;



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

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

Наверх





Память: 0.59 MB
Время: 0.044 c
2-1129817011
Molchanov
2005-10-20 18:03
2005.11.13
CreateProcess


2-1129799690
Duffik
2005-10-20 13:14
2005.11.13
Проверка на наличие


1-1130242650
DelphiLexx
2005-10-25 16:17
2005.11.13
Группа кнопок


2-1129569313
Bogdan1024
2005-10-17 21:15
2005.11.13
типо createprocess


4-1126375396
Mister Twister
2005-09-10 22:03
2005.11.13
Опасен ли CM_RECREATEWND?





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский