Quantcast
Channel: Undocumented Matlab
Viewing all articles
Browse latest Browse all 219

Solving a Matlab MCOS bug

$
0
0

A few days ago, one of my consulting clients asked me to help him with a very strange problem: he had a Matlab class having a constant property that holds a reference to some handle class object. The problem was that when he tried to modify the property’s inner values he got Matlab run-time errors because the inner value apparently remained unmodified!

Here is a distilled version of my client’s classes:

classdef (Abstract) MainClass
    properties (Constant)
        inner = InnerClass
    end
    methods (Static)
        function setInnerValue(newValue)
            MainClass.inner.value1 = newValue;
        end
    end
end
 
classdef InnerClass < handle
    properties
        value1
        value2
    end
end

And the strange run-time behavior:

>> MainClass.inner.value1 = 5
MainClass =
    inner: [1x1 struct]
 
>> MainClass.inner.value2  % causes a strange run-time error!
Reference to non-existent field 'value2'.
 
>> MainClass.inner.value1  % strange - value1 appears unmodified!
ans =
     []
 
>> MainClass.inner  % strange - value1 appears ok here, but where is value2 ?!
ans =
    value1: 5
 
>> MainClass.setInnerValue(7)  % another strange run-time error!
Reference to non-existent field 'setInnerValue'.
 
>> clear classes  % let's try it afresh...
>> MainClass.setInnerValue(7)  % looks ok, no error...
>> MainClass.inner   % strange - now we have both value1 & value2, but value1 is not updated!
ans =
  InnerClass with properties:
 
    value1: []
    value2: []
 
>> MainClass.inner.value1 = 9   % one last attempt, that also fails!
MainClass =
    inner: [1x1 struct]
 
>> MainClass.inner
ans =
  InnerClass with properties:
 
    value1: []
    value2: []
 
>> MainClass.inner.value1
ans =
     []

Understanding the buggy behavior

What the heck is going on here? did Matlab’s MCOS flip its lid somehow? Well, apparently not. It turns out that all these strange behaviors can be attributed to a single Matlab oddity (I call it a “bug”) in its class object system (MCOS) implementation. Understanding this oddity/bug then leads to a very simply workaround.

The underlying problem is that Matlab does not understand MainClass.inner.value1 to mean “the value1 property of the inner property of the MainClass class”. Matlab does understand MainClass.inner to mean “the inner property of the MainClass class”, but adding another dereferencing level (.value1) in the same Matlab expression is too complex for MCOS, and it does not properly understand it.

This being the case, Matlab’s internal interpreter reverts to the simplistic understanding that MainClass.inner.value1 means “the value1 field of the struct inner, which is itself a field of the outer struct named MainClass“. In fact, this creates a new struct variable named MainClass in our current workspace. Still, due to Matlab’s internal precedence rules, the MainClass class overshadows the new variable MainClass, and so when we try to read (as opposed to update) MainClass.inner we are actually referencing the inner reference handle of the MainClass class, rather than the corresponding field in the new struct. The reference handle’s value1 property remains unmodified because whenever we try to set MainClass.inner.value1 to any value, we’re just updating the struct variable in the local workspace.

Unfortunately, no run-time warning is issued to alert us of this. However, if we load MainClass.m in the Matlab editor, we get a somewhat-cryptic MLint warning that hints at this:

MLint warning about class object appearing as a struct

Confusing? indeed!

The workaround

Now that we understand the source of all the problems above, the solution is easy: help Matlab’s internal interpreter understand that we want to reference a property of the inner object reference. We do this by simply splitting the 3-element construct MainClass.inner.value1 into two parts, first storing innerObj = MainClass.inner in a temporary local variable (innerObj), then using it to access the internal innerObj.value1 property:

innerObj = MainClass.inner;
innerObj.value1 = 7;

Hopefully, in some future Matlab release, MCOS will be smarter than today and automatically handle multi-element MCOS constructs, as well as it currently does for 2-element ones (or multi-element Java/.Net/COM constructs).

Have you ever encountered any other Matlab bug that appears perplexing at first but has a very simple workaround as above? If so, then please share your findings in a comment below.

 
Related posts:
  1. Solving a Matlab hang problem A very common Matlab hang is apparently due to an internal timing problem that can easily be solved. ...
  2. Solving a MATLAB bug by subclassing Matlab's Image Processing Toolbox's impoint function contains an annoying bug that can be fixed using some undocumented properties....
  3. Solving an mput (FTP) hang problem Matlab may hang when using passive FTP commands such as mput and dir. A simple workaround is available to fix this. ...
  4. Types of undocumented Matlab aspects This article lists the different types of undocumented/unsupported/hidden aspects in Matlab...
 

Viewing all articles
Browse latest Browse all 219

Trending Articles