【发布时间】:2016-07-18 09:19:15
【问题描述】:
MATLAB 句柄类对象是deleted when they go out of scope。我有可以在应用程序的不同部分重用的对象,但是当它们不再在任何地方使用时我想销毁它们。 MATLAB 的内置生命周期行为允许我执行此操作,而无需维护任何额外的全局列表来跟踪可能使用该对象的内容。
但是我有一种情况,我认为应该超出范围的对象仍然触发事件侦听器回调,这些回调作为对象析构函数的一部分被删除。我知道我认为该对象的最后一个句柄应该存储在哪里,当我在那里检查时,确实该句柄已被清除。所以在其他地方一定有这个句柄的实例。
我的应用程序是一个复杂的对象网络,存储为其他对象的属性。我能做些什么来帮助追踪该对象的句柄在范围内的存储位置吗?
示例
首先设置一个带有事件监听的句柄类:
classdef Yard < handle
events
RollCall
end
end
然后是一个句柄类,它通过显示一些文本然后通知自己的事件来响应来自Yard 对象的RollCall 事件:
classdef Kennel < handle
properties
id
yardListener
end
events
RollCall
end
methods
function obj = Kennel(yard,id)
obj.yardListener = event.listener(yard,'RollCall',@obj.Report);
obj.id = id;
end
function Report(obj,~,~)
fprintf('Kennel %d is in the yard\n', obj.id);
notify(obj,'RollCall');
end
end
end
最后是一个类,它通过显示一些文本来响应来自Kennel 对象的RollCall 事件:
classdef Dog
properties
name
kennel
kennelListener
end
methods
function obj = Dog(name,kennel)
obj.name = name;
obj.kennel = kennel;
obj.kennelListener = event.listener(kennel,'RollCall',@obj.Report);
end
function Report(obj,kennel,~)
fprintf('%s is in kennel %d\n', obj.name, kennel.id);
end
end
end
现在将这些类的一些实例添加到工作区:
Y = Yard;
% Construct two Dog objects, in each case constructing a new Kennel object to pass to the constructor
dogs = [Dog('Fido',Kennel(Y,1)) Dog('Rex',Kennel(Y,2))];
% Construct a third Dog, reusing the Kennel object assigned to dog(1)
dogs(3) = Dog('Rover',dogs(1).kennel);
我现在在范围内有两个Kennel 对象,其句柄在数组dogs 中的Dog 对象的属性中引用。调用 notify(Y,'RollCall') 会产生以下输出:
Kennel 2 is in the yard
Rex is in kennel 2
Kennel 1 is in the yard
Rover is in kennel 1
Fido is in kennel 1
如果原来的两个Dogs 被删除,那么 kennel 2 就会超出范围,但 kennel 1 仍然处于活动状态,因为它仍然被剩余的 Dog 引用:
>> dogs = dogs(3);
>> notify(Y,'RollCall')
Kennel 1 is in the yard
Rover is in kennel 1
但是,如果我在删除剩余的 Dog 之前在范围内的其他位置隐藏了 kennel 1 的附加句柄,那么它将保持活动状态:
>> t = timer('UserData',dogs(1).kennel);
>> clear dogs
>> notify(Y,'RollCall')
Kennel 1 is in the yard
问题是,如果我不知道这个额外的引用是在何时何地创建的,以及为什么它没有被删除,我可以做些什么来调试对象的存在?
【问题讨论】:
-
您是在专门讨论图形句柄吗?如果是这样,这可能是一个不错的起点:
A = findall(0);或B = findobj;。 -
您是否尝试过显式破坏您的对象,而不是依靠 MATLAB 来为您完成? minimal reproducible example 会很好地解决这个问题。
-
@Dev-iL - 不,不幸的是,我只讨论用户定义类的对象的句柄。与其他句柄类对象的
findall类比将是理想的。 -
@excaza - 要决定显式销毁一个对象,我必须知道应用程序状态中的任何内容都不需要它。将生命周期附加到范围内的存在在许多意义上是一个完美的解决方案,并且要求整个代码库维护一些集中列表,然后负责显式对象销毁,这无异于为函数中的工作空间创建 MATLAB 框架的并行模型调用栈。我的问题涉及 MATLAB 的内置功能是否能够解决我的问题而不在如此低的级别上扩展它......
-