Delphi 能告诉我抛出异常的例程的名称吗?

jogvjijk  于 2023-01-20  发布在  其他
关注(0)|答案(7)|浏览(111)

我知道如何在 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;

我将收到一条消息/object/anything,它指示我在“bla”中引发了错误“x”。
我知道madexcept,有没有另一种方法来捕捉异常?
我用的是 Delphi 7.解决方案也可以适用于其他Delphi版本.

l0oc07j2

l0oc07j21#

您可以使用JclDebug.pas单元中的ProcByLevel函数,该单元是JCL库的一部分。
在使用之前,您必须从Ide菜单工具-〉jcl选项激活选项'Insert JDBG data into the binary'

然后你可以这样使用它

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;

结果是这样的

hfwmuf9z

hfwmuf9z2#

EurekaLog也是一个优秀的工具,与MadExcept不相上下。
如果您有EurekaLog:

uses
  EDebugInfo;

procedure TMyObject.SomeMethod();
begin
  Writeln('my name is: ' + __FUNCTION__); 
end;

还有__FILE____MODULE____UNIT____LINE__,以及一个通用的GetLocationInfoStr函数。
然而:
1.只有在使用一些调试信息(以及corresponding debug info provider is enabled)进行编译时,它才能工作:

  • EurekaLog有自己的调试信息格式,可以选择压缩(实际上不推荐压缩,因为这会花费更多的内存和CPU)。
  • 它还支持JCL/JEDI、Synopse/MAB以及. map、. tds/TD32、. dbg和. pdb。

1.它不是一个常量。名字将被动态查找,所以它有一些运行时间开销。

cyej8jka

cyej8jka3#

像MadExcept这样的库向应用程序添加元数据,以便它可以将地址Map到单元和函数名。
Delphi 不会自动执行此操作,也没有提供直接执行此操作的方法,它只是提供引发异常的地址。
以下是一些替代方法:

有了它们,您可以在发生异常时获得调用堆栈的快照。

5sxhfpxr

5sxhfpxr4#

还可以看看JCLDebug的JCLLastExceptStackListToStrings(),它为您提供了一个很好的异常点堆栈转储。
就像TheNewbie说的:可以通过将TApplication.OnException设置为错误处理程序的地址来实现。

6fe3ivhb

6fe3ivhb5#

不, Delphi 没有任何内置的“获取当前函数名”功能,MadExcept或类似产品可能是在错误报告中获取有意义的名称的最佳方法。

jfgube3f

jfgube3f6#

当然,MadExcept是目前为止我发现的最好的解决方案,但是如果你的需求不是太花哨,而且你的项目是商业化的,那么你应该检查项目JEDI的JCL(特别是JclDebug.pas)。在那里你会发现很多有用的例程。它支持.MAP文件,TurboDebugger符号,等等。而且,用它你可以嵌入调试信息(就像MadExcept一样)。
您可能还需要研究一下TApplication.OnException(以及相关的)。

imzjd6km

imzjd6km7#

正如其他人所说... JCL有一些很好的特性...
在您的应用程序中...您需要设置一些信息来获得必要的堆栈框架的挂钩...
项目--〉编译器-〉堆栈帧...我还检查了所有调试并添加了以下内容...项目-〉选项-〉链接器-〉Map文件(选择详细信息)/包含TD 32调试信息
在我的记录器单位...我有这个...你必须有你自己的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.

相关问题