【问题标题】:Get functionname from the functionpointer?从函数指针获取函数名?
【发布时间】:2012-01-13 07:31:29
【问题描述】:

我有一个指向这样的函数的指针。

TTestEvent = function(): Boolean;

procedure ExecuteTest(aTest: TTestEvent; aType: String);
begin
  if aTest then
    NotifyLog(aType + ' success')
  else
    TestError(aType + ' failed');
end;

// Call the test
procedure TestAll;
begin
  ExecuteTest(LoadParcels, 'LoadParcel');
end;

但是从函数指针 aTest 中提取函数名会更好。

所以不是

aType + ' success'

我想要类似的东西

ExtractName(aTest) + ' success'

这可以在 Delphi 2007 中完成吗?

【问题讨论】:

  • 看起来是个使用属性的好地方。
  • @Pol:仅对实现高级 Rtti 功能的最新 Delphi 版本有效。
  • 我只想要一些简单的东西。所以答案是不可能的,除非我使用 JCLDebug 或 MadExcept 对我来说没问题。

标签: delphi function-pointers delphi-2007


【解决方案1】:

如果您使用我们的一些开源类,您将能够找到任何符号的名称。

您必须在构建可执行文件时创建一个.map 文件,方法是在您的项目选项中设置“详细地图”。

然后您可以将.map.exe 一起传送,或者将.map 压缩为我们专有的.mab 格式,该格式可以附加到.exe。对于此任务,.mab 格式比 .zip 或其他格式更有效:它比原始的 .map 文件小大约 10 倍(也就是说,比 JCLDebug 或 MaxExpect 提供的文件小得多,而且小得多比使用标准的“远程调试符号”嵌入项目选项)。

然后您可以使用TSynMapFile 类从.map 文件中检索调试信息,或者嵌入到.exe 中的信息:

function ExtractName(aSymbolAddress: pointer): string;
var i: integer;
begin
  with TSynMapFile.Create do // no name supplied -> will read from .exe
  try
    i := FindSymbol(aSymbolAddress);
    if i>=0 then
      result := Symbols[i].Name else
      result := '';
  finally
    Free;
  end;
end;

它适用于函数名称,也适用于任何其他符号,如方法或全局变量。

请参阅this blog article 了解课程。请注意,即使我们的 mORMot 框架或其日志功能使用它,您也不需要使用整个框架(只需 SynCommons.pasSynLZ.pas 单位)。请参阅“SQLite3\Samples\11 - Exception logging”子文件夹中的Map2Mab.dpr 程序,将 .map 文件内容嵌入到 .exe 中。

【讨论】:

  • +1 不错的解决方案! .map/.mab 文件可能被篡改。如何解决安全问题?我应该发布一个新问题吗?
  • @menjaraz 如果您将 .mab 内容嵌入/附加到 .exe(正如我在解决方案中建议的那样),它不会被轻易篡改,并且会简化部署(只有一个 .exe) .而且您将能够为您的应用程序添加一些不错的功能,例如带有堆栈跟踪的异常日志记录(包括源代码行号)。
  • @ArnaudBouchez 为什么篡改很难?我并不是说这个很重要,因为我相信任何时候将地图附加到 exe 中,黑客都很容易阅读它。我们个人使用 madExcept 但不分发 .mad 文件。向用户发送带有地址的错误报告电子邮件,然后我们可以从中生成有意义的堆栈跟踪,因为我们确实拥有所有已发布版本的 .mad 文件。
  • @DavidHeffernan 您可以轻松地为我们的 .mab 内容添加一些加密(因为提供了所有源代码),以保护隐私。并且篡改 .exe 二进制内容将比更改 .map 文本文件更困难。对于 hexa 中的堆栈跟踪,如果没有 .map/.mab 可用,它是我们的 TSynLog 的默认值:在这种情况下,您可以直接从我们的 log viewer tool 中检索符号,从“.map”按钮。但是在日志文件中,这没有那么吸引人。
【解决方案2】:

使用内置功能无法做到这一点。为了从地址中获取函数名,您需要知道可执行文件的映射。除非您采取措施添加它,否则它不是可执行文件的一部分。

JclDebug 和 madExcept 等调试工具可提供您正在寻找的功能。

【讨论】:

    【解决方案3】:

    您可以实现基于Dictionary 的注册机制

    • 函数指针为Key
    • 函数名称为Value

    ExtractName 将是字典的一个方法。

    如果需要,不要忘记让它成为线程安全的。

    【讨论】:

      猜你喜欢
      • 2012-11-15
      • 2010-09-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多