简体   繁体   English

如何跟踪OLE自动化对象的_AddRef / _Release调用

[英]How to trace _AddRef / _Release calls for OLE Automation objects

(Delphi XE2 update 4) (Delphi XE2更新4)

I'm trying to get a big Microsoft Word OLE automation unit I inherited (based on the early binding TWordApplication and interfaces from the WordXP / Word2010 units) to close WINWORD.EXE when all references have been released. 我试图获得一个我继承的大型Microsoft Word OLE自动化单元(基于早期绑定TWordApplicationWordXP / Word2010单元的接口),以便在所有引用都已发布时关闭WINWORD.EXE

So far, it looks like I did catch a couple of reference leaks: most references are properties or local variables. 到目前为止,看起来我确实捕获了几个引用泄漏:大多数引用都是属性或局部变量。

Some usage scenario's however still keep WINWORD.EXE open. 但是,某些使用方案仍然保持WINWORD.EXE打开。

A few of the fixes indicate I should favour local variables in stead of chains from 一些修正表明我应该支持局部变量而不是链

procedure TOffice_10_XP_WordInterface.AddDocument;
var
  WordApplicationDocuments: Documents;
begin
  WordApplication_Documents.Add(EmptyParam, EmptyParam, EmptyParam, EmptyParam);
end;

to

procedure TOffice_10_XP_WordInterface.AddDocument;
var
  WordApplicationDocuments: Documents;
begin
  WordApplicationDocuments := WordApplication_Documents;
  WordApplicationDocuments.Add(EmptyParam, EmptyParam, EmptyParam, EmptyParam);
end;

based on a WordApplication_Documents property that calls this function: 基于调用此函数的WordApplication_Documents属性:

function TOffice_10_XP_WordInterface.GetWordApplication_Documents: Documents;
begin
  Result := WordApplicationReference.Documents;
  if not Assigned(Result) then
    raise EAccessViolation.Create('Documents');
end;

The properties are there to make the EAccessViolation messages more readable than the $C0000005 errors you get in the debugger. 这些属性使EAccessViolation消息比您在调试器中获得的$ C0000005错误更具可读性。

I'm wondering about generic (since I'll probably need this for other automation projects as well) ways to monitor _AddRef and _Release calls. 我想知道泛型(因为我可能还需要这个用于其他自动化项目)监视_AddRef_Release调用的方法。

I did take a look at these links: 我确实看过这些链接:

A tedious way that gets you going is this: 让你前进的繁琐方式是这样的:

Put breakpoints of all _AddRef and _Release calls in the Delphi System unit that are not inside TInterfacedObject specific methods. 在Delphi System单元中放置TInterfacedObject特定方法内的所有_AddRef_Release调用的断点。

Now eliminate (using conditional expressions) all the interfaces that are not part of Delphi ( EAX contains the vTable pointer for each interface). 现在消除(使用条件表达式)所有不属于Delphi的接口( EAX包含每个接口的vTable指针)。

  1. Start debugging your application with a simple run/exit without doing much actual functionality: 使用简单的运行/退出开始调试应用程序,而无需执行太多实际功能:
  2. Before tracing in each call, make a note of the EAX value. 在跟踪每个调用之前,请记下EAX值。
  3. If you end up in any of these methods: NopRelease , NopAddref , TInterfacedObject._AddRef , TInterfacedObject._Release , MemRelease , MemAddRef then add the EAX value to a conditional breakpoint instruction for all of the breakpoints like below. 如果您最终使用以下任何方法: NopReleaseNopAddrefTInterfacedObject._AddRefTInterfacedObject._ReleaseMemReleaseMemAddRef然后将EAX值添加到所有断点的条件断点指令,如下所示。

Example conditional breakpoint expression for my application: 我的应用程序的示例条件断点表达式:

(EAX <> $401E58) and (EAX <> $54AD14) and (EAX <> $4A7C88) ...

This method has a lot of drawbacks, but it gets you going. 这种方法有很多缺点,但它会让你前进。

Drawbacks: 缺点:

  • There are limitations on the length of the conditional breakpoint expression. 条件断点表达式的长度存在限制。 Which means that if you continue to add and (EXA <> $xxxx) portions, the debugger will ignore those without indicating a warning. 这意味着如果继续添加and (EXA <> $xxxx)部分,调试器将忽略那些而不指示警告。
  • You loose the setting if you exit Delphi without saving your desktop 如果在不保存桌面的情况下退出Delphi,则会松开设置
  • It takes a lot of time to setup 设置需要很长时间

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM