Может ли Delphi сказать мне название процедуры, которая вызвала исключение? - PullRequest
3 голосов
/ 10 ноября 2010

Я знаю, как перехватывать исключения в delphi (try..except / finally и e.message), но я хочу знать, существует ли механизм обработки исключений, который может вызывать исключение, а также имя подпрограммы, которая его вызвала,Например,

procedure/function bla();//this can be in a unit/class
begin
 code....
 an error  is raised here -> inside or not of an try-except/finally block 
end;

, и я получу сообщение / объект / все, что указывает на то, что ошибка 'x' возникла в 'bla'.

Я знаю о madexcept, естьеще один способ отловить исключения?

Я использую Delphi 7. Решение может быть применимо и к другой версии Delphi.

Ответы [ 7 ]

7 голосов
/ 10 ноября 2010

EurekaLog также отличный инструмент, наравне с MadExcept.

7 голосов
/ 10 ноября 2010

Вы можете использовать функцию ProcByLevel из устройства JclDebug.pas, которое является частью библиотеки JCL .

, прежде чем использовать ее, вы должны активировать опцию 'Insert JDBG data into the binary' изИнструменты Ide Menu-> Параметры jcl.

alt text

, и затем вы можете использовать его таким образом

Uses
 JclDebug;

procedure TForm18.Button1Click(Sender: TObject);
begin
    try

       raise  Exception.Create('Hello from '+ProcByLevel(0));
    except
         on e : Exception do
         ShowMessage(e.Message);
    end;
end;

, и результат будет примерно таким

alt text

6 голосов
/ 10 ноября 2010

Библиотеки, такие как MadExcept, добавляют метаданные в приложение, чтобы оно могло сопоставить адрес с именем устройства и функции.

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

Некоторые альтернативы делать то, что вы хотите:

С их помощью вы можете получить снимок стека вызовов при возникновении исключения.

5 голосов
/ 10 ноября 2010

Также посмотрите на JCLLastExceptStackListToStrings () JCLDebug, который дает вам хороший дамп стека точки исключения.

И, как заметил TheNewbie: вы получаете это, устанавливая TApplication.OnException в качестве адреса вашего обработчика ошибок.

3 голосов
/ 10 ноября 2010

MadExcept - это лучшее решение, которое я нашел на данный момент, конечно, но если ваши потребности не слишком причудливы и ваш проект коммерческий, вам следует проверить JCL проекта JEDI (особенно JclDebug.pas).Там вы найдете много полезных процедур.Он поддерживает файлы .MAP, символы TurboDebugger и т. Д. Кроме того, с его помощью вы можете встраивать отладочную информацию (как в MadExcept).

Возможно, вы также захотите заглянуть в TApplication.OnException (и связанные с ним).

3 голосов
/ 10 ноября 2010

Нет, в Delphi нет встроенной функции «получить имя текущей функции». MadExcept или аналогичные продукты, вероятно, являются лучшим способом получения значимых имен в отчетах об ошибках.

2 голосов
/ 11 декабря 2013

Как уже говорили другие ... У JCL есть несколько приятных функций ...

В вашем приложении ... Вам нужно настроить некоторую информацию, чтобы получить необходимый стековый фрейм для крючка ...
Project -> Compiler-> Stack Frames ... Я также проверил всю отладку и добавил следующее ... Project-> Options-> Linker-> Map map (Выбрать подробный) / Включить TD32 отладочную информацию

В моем устройстве Logger ... У меня есть это ... У вас должен быть свой собственный TLogger ..., который сохраняет информацию для вас ...

use
  JclDebug, JclHookExcept;


procedure HookGlobalException(ExceptObj: TObject; ExceptAddr: Pointer; OSException: Boolean);
var
  a_List: TStringList;
  a_Error: string;
begin
  if Assigned(TLogger._Instance) then
  begin
    a_List := TStringList.Create;
    try
      a_List.Add(cStar);
      a_Error := Exception(ExceptObj).Message;
      a_List.Add(Format('{ Exception - %s }', [a_Error]));
      JclLastExceptStackListToStrings(a_List, False, True, True, False);
      a_List.Add(cStar);
      // save the error with stack log to file
      TLogger._Instance.AddError(a_List);
    finally
      a_List.Free;
      Raise Exception.Create(a_Error);
    end;
  end;
end;

initialization
  Lock := TCriticalSection.Create;
  Include(JclStackTrackingOptions, stTraceAllExceptions);
  Include(JclStackTrackingOptions, stRawMode);

  // Initialize Exception tracking
  JclStartExceptionTracking;

  JclAddExceptNotifier(HookGlobalException, npFirstChain);
  JclHookExceptions;

finalization
  JclUnhookExceptions;
  JclStopExceptionTracking;
  Lock.Free;

end.
...