1

これはこの質問にいくらか関連していますが、完全ではありません。

私には2つのクラスが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ますが、それはのデストラクタで処理されると思いましたTimerWrapperAmroの醜いが簡単な回避策を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が今適切になくなっているのを見つけるでしょう。

これがバグであるかどうかはわかりませんが、かなり紛らわしいと思います。との違いはcleardeleteおそらくより適切に文書化される可能性があります。

回避策としては、明示的に呼び出すのは大きな苦痛ではありませんが、delete誤って呼び出した場合にクリーンアップするのは少し面倒ですclear。メッセージ#4ではなく、リンクしたスレッドからのメッセージ#5の提案は、より一般的で堅牢だと思います。

リンクした別のスレッドで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 に答える