Undocumented Matlab
  • SERVICES
    • Consulting
    • Development
    • Training
    • Gallery
    • Testimonials
  • PRODUCTS
    • IQML: IQFeed-Matlab connector
    • IB-Matlab: InteractiveBrokers-Matlab connector
    • EODML: EODHistoricalData-Matlab connector
    • Webinars
  • BOOKS
    • Secrets of MATLAB-Java Programming
    • Accelerating MATLAB Performance
    • MATLAB Succinctly
  • ARTICLES
  • ABOUT
    • Policies
  • CONTACT
  • SERVICES
    • Consulting
    • Development
    • Training
    • Gallery
    • Testimonials
  • PRODUCTS
    • IQML: IQFeed-Matlab connector
    • IB-Matlab: InteractiveBrokers-Matlab connector
    • EODML: EODHistoricalData-Matlab connector
    • Webinars
  • BOOKS
    • Secrets of MATLAB-Java Programming
    • Accelerating MATLAB Performance
    • MATLAB Succinctly
  • ARTICLES
  • ABOUT
    • Policies
  • CONTACT

Solving a Matlab MCOS bug

December 2, 2015 10 Comments

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

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!
(However, refer to the reader comments below, which provide insight into the reasoning of what’s going on here, and contend that this is actually the expected behavior. I will let the readers decide for themselves whether they agree or not.)

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;

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...
  5. Fixing Matlab's actxserver – Matlab's COM (ActiveX) server behavior can be fixed in a couple of useful manners. ...
  6. Matlab compiler bug and workaround – Both the Matlab compiler and the publish function have errors when parsing block-comments in Matlab m-code. ...
MCOS Pure Matlab Undocumented feature
Print Print
« Previous
Next »
10 Responses
  1. Sven December 2, 2015 at 12:24 Reply

    There was something like this bug in R2015a, which seems to have been fixed in R2015b.
    In order to access the elements of a cell-type variable, you would first need to store a copy of that variable locally.

    T = cell2table({'a';'b';'c'},'Var',{'myCell'})
    sprintf('%s,',T.myCell{:})
    ans =
    a,b,c,

    T = cell2table({'a';'b';'c'},'Var',{'myCell'}) sprintf('%s,',T.myCell{:}) ans = a,b,c,

    The above now works in 2015b. In 2015a however, the result was:

    sprintf('%s,',T.myCell{:})
    ans =
    a,

    sprintf('%s,',T.myCell{:}) ans = a,

    Whereas you could work around with:

    tmpCell = T.myCell;
    sprintf('%s,',tmpCell{:})
    ans =
    a,b,c,

    tmpCell = T.myCell; sprintf('%s,',tmpCell{:}) ans = a,b,c,

    • Sven December 2, 2015 at 12:25 Reply

      And to clarify: the above bug was limited to “cell-typed variables of *tables*”.

  2. Dave Foti December 2, 2015 at 14:12 Reply

    I can understand Yair’s confusion, but there is a simple explanation the behavior described in this post (with Constant properties). MATLAB doesn’t have variable declarations. When a name appears on the left of an equal sign, that statement always create a variable from the left-most name. Try “MainClass.inner = 1” and you will see that it doesn’t matter how complex the indexing expression is, assignment always introduces a new variable that hides any function or class of the same name. In this case the dot indexing means that MainClass will be a struct. It is important that variables have highest precedence so that scripts and functions don’t have to worry about collisions between the variable names used in the code and functions and classes on the path (a set of names that is very large and always growing).

    Reference to a name that has not been introduced as a variable will find the class. It doesn’t matter how many dots you have or how complex the indexing expression is. Here are some functions you can try that show how MATLAB consistently treats assignment as creating a variable. Note that the last two functions produce the same results whether or not MainClass exists on the path.

    function useClassConstants
       X = MainClass.inner  % MainClass is not a variable, so find inner property of MainClass class
       Y = MainClass.inner.value1 
    end

    function useClassConstants X = MainClass.inner % MainClass is not a variable, so find inner property of MainClass class Y = MainClass.inner.value1 end

    function createStruct1
       MainClass.inner = 2 % Create a struct variable named MainClass
       isa(MainClass, 'struct')
    end

    function createStruct1 MainClass.inner = 2 % Create a struct variable named MainClass isa(MainClass, 'struct') end

    function createStruct2
       MainClass.inner.value1 = 3.5 % Create a struct variable named MainClass
       isequal(MainClass.inner.value1, 3.5) % See that we are only using this struct
    end

    function createStruct2 MainClass.inner.value1 = 3.5 % Create a struct variable named MainClass isequal(MainClass.inner.value1, 3.5) % See that we are only using this struct end

    This comes down to the fact that preserving the meaning of variables independent of what is on the path is considered more important than making it easy to create mutable per-class state (which is often problematic anyway because it can lead to unwanted cross-talk between applications that share the same libraries).

    • Yair Altman December 2, 2015 at 15:21 Reply

      @Dave – thanks for your clarification, but the inconsistency here between the assignment and reference precedence rules is confusing. I contend that the following precedence rule might be more intuitive and consitent in such cases, while still preserving the default behavior for the remainder of the cases:

      1. try to understand MainClass (in both assignment and referencing) as referring to variable MainClass on the local workspace. If successful then continue to use this variable.
      2. otherwise, try to understand MainClass as a class/package name. If successful and no error, then continue to use this. Note that this does not break your requirement for MainClass=5 to override the class definition and create a local variable named MainClass, because assigning to a class is illegal and therefore raises an error and falls-through to the following rule:
      3. otherwise, in an assignment create a new workspace variable named MainClass, and in a reference raise an error about trying to use an unrecognized identifier.

      These precedence rules will ensure that variables always take precedence over function/class/package names (as you have rightfully pointed out), but only when they exist – otherwise the existing function/class/package name should obviously take precedence over the non-existing variable. The behavior now becomes fully consistent across assignment and reference, and I think is much more intuitive in run-time than the current situation.

      • Dave Foti December 3, 2015 at 07:22

        Hi Yair,
        The problem is that it isn’t enough for “MainClass = 1” to ensure that MainClass is a variable. As long as structs have existed in MATLAB, it has been possible to create structs using the syntax “MainClass.inner = 1” just as numeric arrays can be created using indexing as in “X(1:10) = 1” Thus, your proposed rules would still mean that a function or script (like the 2 createStruct examples I provided) could be written using local struct variables that later got re-interpreted as referring to a class and its property that happened to be on the path.

  3. Brad Stiritz December 2, 2015 at 21:02 Reply

    Hi Yair, thanks for a super-interesting post. Thanks to Dave as well for the helpful clarification. Just to clarify your workaround, Yair, here’s a revised implementation of the static function, and the expected result
    produced by the new code:

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

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

    >> MainClass.setInnerValue(5)
    >> MainClass.inner
    ans = 
      InnerClass with properties:
        value1: 5
        value2: []

    >> MainClass.setInnerValue(5) >> MainClass.inner ans = InnerClass with properties: value1: 5 value2: []

    • Yair Altman December 3, 2015 at 00:16 Reply

      @Brad – indeed so 🙂

  4. alexandre December 4, 2015 at 04:10 Reply

    cool post!

    I am confused about the following point:

    The inner class is declared inside the ‘constant’ properties – why would we be assigning to it in the first place? It seems to me that this is key for a problem to occur (there is no other attribute that I can see that could be accessed via the static function call – http://se.mathworks.com/help/matlab/matlab_oop/property-attributes.html)

    Reading the docs above suggeststhat Constant properties can be modified (but not by sub-classes). But this article suggests that they should be set at definition and not touched thereafter: http://se.mathworks.com/help/matlab/matlab_oop/properties-with-constant-values.html.

    So are matlab (Constant) properties what other OO languages call ‘static’ properties?

    • Yair Altman December 4, 2015 at 04:16 Reply

      The property is constant in the sense that its reference handle remains unmodified after being set, but its inner properties are not constant. It’s like saying that a company’s ID remains constant, but its employees, phone number, and physical address may possibly change over time. Or like saying that a house address remains constant but its occupants change over time.

      Related post: https://undocumentedmatlab.com/blog/handle-object-as-default-class-property-value

  5. Jeroen Boschma January 7, 2016 at 04:35 Reply

    Hi Yair,

    I think this is certainly not a simple MCOS parser bug, even not a bug at all, but since I have limited knowledge about the inner things of MATLAB classes I may be on thin ice here…

    Try the following as your very first statement:

    MainClass.inner.value2
    ans =
         []

    MainClass.inner.value2 ans = []

    So that rules out that there is only a simple MCOS parser bug just because there would be too many dereferencing levels. Since there is no variable MainClass, MATLAB correctly dereferences all levels within the class MainClass.

    The underlying problem, I think, is that you cannot change class definitions, only instances of classes. What in this case happens is the following:

    1) Within ‘setInnerValue()’ there is no variable named MainClass, and MATLAB detects the reference to the class, correctly taking all reference levels into account (my example above shows that this is not the problem).
    2) MATLAB detects the assignment statement.
    3) MATLAB falls back on the rule “modifying class definitions (i.e. its properties) is not possible”.
    4) MATLAB falls back on the only remaining option: create a new struct variable ‘MainClass’ and execute the assignment.

    So I think the bottom line is that MATLAB has a strict interpretation of “modifying class definitions is not possible”, and that therefore every direct assignment via the class definition is prohibited. This is not a bug at all in my opinion, but you end up in a discussion how tight the underlying fields of ‘inner’ are related to MainClass itself. The fact that you can change the fields of ‘inner’ using a workaround does not mean that MATLAB should allow doing this directly via the class definition itself. For this matter, I tend to agree with MATLAB’s choice.

Leave a Reply
HTML tags such as <b> or <i> are accepted.
Wrap code fragments inside <pre lang="matlab"> tags, like this:
<pre lang="matlab">
a = magic(3);
disp(sum(a))
</pre>
I reserve the right to edit/delete comments (read the site policies).
Not all comments will be answered. You can always email me (altmany at gmail) for private consulting.

Click here to cancel reply.

Useful links
  •  Email Yair Altman
  •  Subscribe to new posts (feed)
  •  Subscribe to new posts (reader)
  •  Subscribe to comments (feed)
 
Accelerating MATLAB Performance book
Recent Posts

Speeding-up builtin Matlab functions – part 3

Improving graphics interactivity

Interesting Matlab puzzle – analysis

Interesting Matlab puzzle

Undocumented plot marker types

Matlab toolstrip – part 9 (popup figures)

Matlab toolstrip – part 8 (galleries)

Matlab toolstrip – part 7 (selection controls)

Matlab toolstrip – part 6 (complex controls)

Matlab toolstrip – part 5 (icons)

Matlab toolstrip – part 4 (control customization)

Reverting axes controls in figure toolbar

Matlab toolstrip – part 3 (basic customization)

Matlab toolstrip – part 2 (ToolGroup App)

Matlab toolstrip – part 1

Categories
  • Desktop (45)
  • Figure window (59)
  • Guest bloggers (65)
  • GUI (165)
  • Handle graphics (84)
  • Hidden property (42)
  • Icons (15)
  • Java (174)
  • Listeners (22)
  • Memory (16)
  • Mex (13)
  • Presumed future risk (394)
    • High risk of breaking in future versions (100)
    • Low risk of breaking in future versions (160)
    • Medium risk of breaking in future versions (136)
  • Public presentation (6)
  • Semi-documented feature (10)
  • Semi-documented function (35)
  • Stock Matlab function (140)
  • Toolbox (10)
  • UI controls (52)
  • Uncategorized (13)
  • Undocumented feature (217)
  • Undocumented function (37)
Tags
ActiveX (6) AppDesigner (9) Callbacks (31) Compiler (10) Desktop (38) Donn Shull (10) Editor (8) Figure (19) FindJObj (27) GUI (141) GUIDE (8) Handle graphics (78) HG2 (34) Hidden property (51) HTML (26) Icons (9) Internal component (39) Java (178) JavaFrame (20) JIDE (19) JMI (8) Listener (17) Malcolm Lidierth (8) MCOS (11) Memory (13) Menubar (9) Mex (14) Optical illusion (11) Performance (78) Profiler (9) Pure Matlab (187) schema (7) schema.class (8) schema.prop (18) Semi-documented feature (6) Semi-documented function (33) Toolbar (14) Toolstrip (13) uicontrol (37) uifigure (8) UIInspect (12) uitools (20) Undocumented feature (187) Undocumented function (37) Undocumented property (20)
Recent Comments
  • Sunham (2 days 20 hours ago): This is an old article, but the issue persists even in 2023. 2023a: z = mat2cell(1:1e6,1,repmat(1,1,1e 6)); f = @() cellfun(‘isempty’, z); g = @() cellfun(@isempty,z);...
  • Yair Altman (12 days 10 hours ago): Robot only runs when you tell it to run a command such as keyPress. If you don’t tell it to run a command, it uses no CPU, so there’s no need to remove the Robot...
  • Eric (12 days 22 hours ago): Hey @Kevin, can you share your code about create group of figures in the AppContainer? The container of multiples uifigures could be an amazing improvement over AppDesigner and its...
  • Elsa Smith (13 days 12 hours ago): I recently used java.awt.Robot to perform GUI testing on MATLAB and found it to be an extremely easy and useful way to control mouse movements.
  • Elsa Smith (13 days 13 hours ago): I’m suspecting that the slow performance of my GUI may be due to the use of java.awt.Robot. Is there a way to cancel/stop/remove the robot after it has been created, or is...
  • Michelle Kline (14 days 6 hours ago): *edit* tip about fopen(), not about fwrite(). ‘Wb’ vs. ‘wb’
  • Michelle Kline (14 days 6 hours ago): Thank you, Yair! With this previously-unknown-to-me tip about fwrite() performance, you have saved me literally hours of processing time. Michelle Kline Department of...
  • Alessandro Beda (26 days 18 hours ago): I found what I think is a bug related to this (tested in R2022 and R2023a). If I add a “ButtonDownFcn” to the plots (see example below), then the modified...
  • Nicholas (28 days 8 hours ago): Yair, Changing the desktop help options did not solve the issue. Though, it’s unclear how I could change these options in the Runtime, if that’s what you meant? I should...
  • Yair Altman (32 days 3 hours ago): @Francisco – this is one of those cases where you should ask MathWorks support. After all, you’re trying to use a supported Matlab functionality when you encountered...
  • Francisco Campos (32 days 15 hours ago): Hello, thanks for all your work that has been immensely useful for those working in the Matlab environment. I have been trying to replace matlabcontrol with the official...
  • Yair Altman (36 days 16 hours ago): Kei – this is possible, I believe that I saw this ability somewhere, a few years ago. I don’t remember exactly where, it will require a bit of research, but...
  • Kei (36 days 18 hours ago): Hello Yair Thank you for this great article. I would like to freeze first two columns in uitable. Do you know if such option is available? Since looks like this option is not available...
  • Andrés Aguilar (40 days 6 hours ago): Hello, has anyone tried to change the language of the DateComboBox? For example English -> French ————&# 8212;—- January -> Janvier April...
  • Yair Altman (49 days 4 hours ago): I posted my treeTable utility 10 years ago for anyone to use freely, on an as-is basis, without any warranty, updates or support. If you need any customization or assistance...
Contact us
Captcha image for Custom Contact Forms plugin. You must type the numbers shown in the image
Undocumented Matlab © 2009 - Yair Altman
This website and Octahedron Ltd. are not affiliated with The MathWorks Inc.; MATLAB® is a registered trademark of The MathWorks Inc.
Scroll to top