官方文档说它们是可选的.我知道COM interop需要每个接口的唯一标识符,但我看到的每个接口示例都有一个GUID,无论它是否与COM一起使用?如果GUID不能与COM一起使用,是否有任何好处?
在将对象的新实例传递给具有对象类实现的接口的const接口参数的方法时,编译器是否应该提示/警告?
编辑:当然样本很容易说明问题.但在现实生活中,它变得更加复杂:如果创建和使用在相隔很远的代码(不同的单元,不同的类,不同的项目)中会怎么样?如果由不同的人维护怎么办?如果非const参数变为常量参数,并且不能检查所有调用代码(因为更改代码的人无法访问所有调用代码),该怎么办?
下面的代码崩溃了,很难找到原因.
首先是日志:
1.Run begin
1.RunLeakCrash
2.RunLeakCrash begin
NewInstance 1
AfterConstruction 0
3.LeakCrash begin
_AddRef 1
4.Dump begin
4.Dump Reference=10394576
4.Dump end
_Release 0
_Release Destroy
BeforeDestruction 0
3.LeakCrash Reference got destroyed if it had a RefCount of 1 upon entry, so now it can be unsafe to access it
_AddRef 1
4.Dump begin
4.Dump Reference=10394576
4.Dump end
_Release 0
_Release Destroy
BeforeDestruction 0
3.LeakCrash end with exception
1.Run end
EInvalidPointer: Invalid pointer operation
Run Code Online (Sandbox Code Playgroud)
然后过早释放实现接口的对象实例的代码:
//{$define all} …Run Code Online (Sandbox Code Playgroud) 首先是问题:为什么删除const UnregisterNode()导致失败,而不是导致失败RegisterNode().
现在的背景:我正在使用Interfaces在Delphi XE中工作,我遇到了一个让我停顿一下的工件,我得出的结论是我真的不明白为什么.
不需要显式释放作为接口访问的对象.当最后一个引用超出范围时,它将被销毁.这似乎很简单.我编写了一个测试用例来显示按预期运行的变量和两个失败的变量.六个测试用例仅限于Register和Unregister方法的Node参数的变体.
按下表单上的单个按钮可创建容器和三个节点.对它们进行操作以演示该程序
该程序创建一些链接到简单容器的简单节点.问题发生在案例#1和#6中.在释放节点时,它会调用containers Unregister()方法.该方法删除指向TList中节点的指针的副本.当在两个失败的情况下离开该方法时,它以Destroy()递归方式再次启动该过程调用该节点的方法,直到发生堆栈溢出.
在有效的四种情况下,Destroy()方法恢复正常,程序将继续正常退出.
失败#1(案例1)
procedure RegisterNode(Node:INode);
procedure UnregisterNode(Node:INode);
Run Code Online (Sandbox Code Playgroud)
Unregister()从TNode.Destroy()方法调用节点似乎影响INode的引用计数导致多次调用Destroy(). 为什么这种情况发生我不明白.当我Register()具有相同样式的参数的节点时,它不会发生.
失败#2(案例6)
procedure RegisterNode(const Node:INode);
procedure UnregisterNode(Node:INode);
Run Code Online (Sandbox Code Playgroud)
这里发生了同样的失败模式.如案例5中那样将const添加到参数列表可防止递归调用Destroy().
代码:
unit fMain;
{
Case 1 - Fails when a node is freed, after unregistering,
TNode.Destroy is called again
Case 2 - Passes
case 3 - Passes
Case 4 - Passes
Case 5 - Passes
Case 6 - Fails the …Run Code Online (Sandbox Code Playgroud)