1

这与this question有些相关,但不完全相关。

我有两个班级,FunctionWrapper并且TimerWrapper

classdef FunctionWrapper < handle
    methods
        function Fcn(obj)
            disp('FunctionWrapper.Fcn was called!');
        end
    end
end

classdef TimerWrapper < handle
    properties
        Timer
    end

    methods
       function obj = TimerWrapper(other_object)
            obj.Timer = timer;
            set(obj.Timer, 'Period', 1);
            set(obj.Timer, 'ExecutionMode', 'fixedSpacing');
            set(obj.Timer, 'TimerFcn', @(event, data) other_object.Fcn);
       end

       function start(obj)
           start(obj.Timer);
       end

       function stop(obj)
           stop(obj.Timer);
       end

       function delete(obj)
           disp('destructor called!');
           delete(obj.Timer);
       end
    end
end

假设我在命令行窗口中执行以下代码:

>> F = FunctionWrapper;
>> T = TimerWrapper(F);
>> clear T %# T's destructor not called
>> timerfind %# just to verify that no, the destructor was never called

   Timer Object: timer-1

   Timer Settings
      ExecutionMode: fixedSpacing
             Period: 1
           BusyMode: drop
            Running: off

   Callbacks
           TimerFcn: @(event,data)other_object.Fcn
           ErrorFcn: ''
           StartFcn: ''
            StopFcn: ''

这里发生了什么?我知道timer需要手动删除对象,但我认为这将在析构函数中处理TimerWrapper。如果不使用Amro 丑陋但直接的解决方法来重载clear命令,有没有办法clear T从工作区中取出?此外,什么都没有引用T,那么为什么存在对它的引用呢?(析构函数从未被调用的事实暗示了这一事实。)这是否隐藏在计时器对象本身中?

4

2 回答 2

2

如果您键入t = TimerWrapper; f = functions(t.Timer.TimerFcn); f.workspace(2),您将看到用于回调的匿名函数的工作区包含对TimerWrapper对象本身的引用。所以那里有一种循环引用,它没有被clear.

鉴于您的设置方式,您可以T通过显式调用析构函数然后调用clear.

T.delete
clear T

clear和之间的区别delete有点令人困惑(无论如何对我来说)。如您所见,clear没有显式调用析构函数。它只是从工作区中删除名称 T。所以T,以及它的底层计时器,在那个时候仍然存在。如果它们不包含对仍然存在的事物的引用,则 MATLAB 将T正确删除,包括调用其析构函数。实际上,由于计时器包含对 的引用(在其回调中)T,该引用仍然存在,因此T不会删除计时器(以及因此)。

您可以使用 找到它(尽管在工作区中没有名称)timerfindall,如果您自己明确删除它使用

tmrs = timerfindall;
delete(tmrs);

你会发现它T现在已经完全消失了。

我不太确定这是一个错误,尽管我觉得这很令人困惑,并且可能会更好地记录和之间的clear区别delete

至于解决方法,我不觉得显式调用很痛苦delete,尽管如果你不小心调用了清理东西会更痛苦clear。我认为来自您链接到的线程中的消息 #5 中的建议,而不是消息 #4,会更普遍和强大。

我认为您不应该clear按照@Amro在您链接到的单独线程中建议的方式重载:尽管如果您明确调用这可能会起作用clear T但如果您调用clear all, 或clear variables. (我刚刚还没有尝试过,但我相信这些语法clear甚至不会遍历工作区中的东西并调用clear每个 - 而是调用clear内部 MATLAB 工作区对象的方法,这会很快让人感到困惑)。

于 2012-05-08T09:47:29.510 回答
0

似乎这可能是因为计时器的回调设置为非默认值。建议的解决方法(参见链接线程的消息#4)是仅在start调用方法时设置回调函数,然后在调用方法时将其设置为 null stop

于 2012-05-07T22:42:22.550 回答