Like any other major software package, Matlab too has its share of bugs. If you ask me, the number of known bugs in Matlab is actually very small compared to the industry standard. Posting bugs online saves the support staff work on duplicates and provides immediate relief for users if the bug happens to have a posted workaround. It also increases transparency, which helps customer loyalty and confidence in the product. Serious engineering work that relies on Matlab for anything from designing cars and planes to trading on stock exchanges needs to be aware of all the current bugs, in order to avoid them in the production code.
Unfortunately, for some reason MathWorks does not publicize all the bugs that it knows about. I know this since there are multiple bugs that I have reported and were confirmed by the competent technical support staff, which do not appear on the online list. I do not know whether this is a deliberate MathWorks policy based on some criteria, but I would hope not and I hope it will be fixed. IMHO, Matlab in general is a very stable system that has absolutely nothing to be ashamed of in terms of the low number, and relatively low-impact, of its open bugs.
Today I write about two internal Matlab bugs that I have recently discovered and reported, along with their workarounds. None of them is really critical, but since neither appears in the official bug parade (as of today), I figured it would do some public good to post them here.
The clf function does not clear javacomponents (1-MNELS1)
The clf function clears the specified figure window (or the current figure [gcf] if no figure handle was specified as input) of any axes and GUI controls. At least, that what it is supposed to do and what it did pretty well until R2012a (Matlab 7.14). Apparently, in R2012b (Matlab 8.0) something broke and controls that are added to the figure window using the javacomponent function are no longer cleared by clf – all the regular Matlab axes and uicontrols are deleted, but not the Java controls.
figure; [jButton, hContainer] = javacomponent(javax.swing.JButton('Click'), [], gcf); drawnow; clf % bug - clf does not delete the jButton/hContainer component from the figure |
There are several possible workarounds:
- Keep the handles of all the relevant Java components, and then delete them directly:
delete(hContainer)
- Use findobj to delete all components, rather than the clf function (we use setdiff to prevent deletion of the figure window itself):
delete(setdiff(findobj(gcf),gcf))
Note that this bug does not occur when using HG2. However, for users who use the still-standard HG1, this bug is still unfixed as of Matlab R2013b Pre-release (which is now available for download for subscribed users).
GUIDE is unusable with dbstop if error (1-MH5KVI)
In R2013a (Matlab 8.1) I encounter a recurring error when attempting to inspect properties of objects in GUIDE, when “dbstop if error” is turned on.
The error happens when I have “dbstop if error” enabled. This is an enormously helpful debugging tool, so I normally have it turned on in my startup.m file. But in R2013a, if I try to inspect an object’s properties in GUIDE, I see a problem. Matlab hits the breakpoint in %matlabroot%/toolbox/matlab/codetools/+internal/+matlab/+inspector/SceneViewerListener.m line 99 due to the fact that isvalid() is not defined for the object, and the inspector window remains blank.
How to reproduce:
- run “dbstop if error” in the Matlab command window
- open a *.fig file in the Matlab command window (e.g., “guide myApplication.fig“)
- right-click and inspect the properties for an axes (for example)
- wait for the breakpoint to occur – “K>>” in the command window; the Editor stops (green arrow) in SceneViewerListener.m line 99
- an empty inspector window is displayed
Analysis:
Because SceneViewerListener is called from Java, not Matlab, the error is thrown as an exception that is trapped by the Java code and therefore does not appear to the user unless “dbstop if error” is on. Here is the full stack trace at the point of error (see this post regarding how to generate the Java stack dump):
K>> dbstack > In SceneViewerListener>SceneViewerListener.isBeingDeleted at 99 K>> st = java.lang.Thread.currentThread.getStackTrace; for idx = 2 : length(st), disp(st(idx)); end com.mathworks.jmi.NativeMatlab.SendMatlabMessage(Native Method) com.mathworks.jmi.NativeMatlab.sendMatlabMessage(NativeMatlab.java:219) com.mathworks.jmi.MatlabLooper.sendMatlabMessage(MatlabLooper.java:120) com.mathworks.jmi.Matlab.mtFeval(Matlab.java:1540) com.mathworks.mlwidgets.inspector.JidePropertyViewTable.isBeingDeleted(JidePropertyViewTable.java:154) com.mathworks.mlwidgets.inspector.JidePropertyViewTable.filterOutInvalidObjects(JidePropertyViewTable.java:170) com.mathworks.mlwidgets.inspector.JidePropertyViewTable.setObjects_MatlabThread(JidePropertyViewTable.java:187) com.mathworks.mlwidgets.inspector.PropertyView.setObject_MatlabThread(PropertyView.java:655) com.mathworks.mlwidgets.inspector.PropertyView.setObject_AnyThread(PropertyView.java:591) com.mathworks.mlwidgets.inspector.PropertyView.access$1300(PropertyView.java:37) com.mathworks.mlwidgets.inspector.PropertyView$RegistryHandler.itemStateChanged(PropertyView.java:698) java.awt.AWTEventMulticaster.itemStateChanged(Unknown Source) com.mathworks.services.ObjectRegistry.fireItemEvent(ObjectRegistry.java:763) com.mathworks.services.ObjectRegistry.setSelected(ObjectRegistry.java:700) com.mathworks.services.ObjectRegistry.setSelected(ObjectRegistry.java:617) com.mathworks.mde.inspector.Inspector.setSelected(Inspector.java:584) com.mathworks.mde.inspector.Inspector.inspectObjectArray(Inspector.java:569) com.mathworks.mde.inspector.Inspector.inspectObjectArray(Inspector.java:520) com.mathworks.mde.inspector.Inspector$11.run(Inspector.java:478) com.mathworks.jmi.NativeMatlab.dispatchMTRequests(NativeMatlab.java:347) |
Workaround:
replace the existing code of SceneViewerListener.m:
>> edit internal.matlab.inspector.SceneViewerListener ... if ~isvalid(selectedObject) beingDeleted = true; elseif isprop(selectedObject,'BeingDeleted') && strcmp('on',selectedObject.BeingDeleted) beingDeleted = true; elseif ~isempty(ancestor(selectedObject,'figure')) && strcmp('on',get(ancestor(selectedObject,'figure'),'BeingDeleted')) beingDeleted = true; else beingDeleted = false; end |
with the following (changed lines are highlighted):
if any(~isobject(selectedObject)) beingDeleted = false;elseif ~isValid beingDeleted = true; elseif isprop(selectedObject,'BeingDeleted') && strcmp('on',selectedObject.BeingDeleted) beingDeleted = true; elseif ~isempty(ancestor(selectedObject,'figure')) && strcmp('on',get(ancestor(selectedObject,'figure'),'BeingDeleted')) beingDeleted = true; else beingDeleted = false; end |
It looks like this bug was apparently fixed in the R2013b Pre-release without needing to modify SceneViewerListener. But if you still encounter this problem you now know what to do.
I have reported another GUIDE-related bug, but I do not have a workaround for this one: If you run the GUI from within GUIDE, and some uncaught error (exception) occurs, then from that moment onward you cannot save any modifications to the figure file in that session.
Do you know of any other undocumented bugs, preferably with workarounds? If so, please post them in a comment here.
I’m not sure if this is an error or a feature that I’m not comprehending…
I’ve started playing around with using Mask Objects (http://www.mathworks.com/help/simulink/slref/simulink.mask.get.html) from a Simulink Mask instead of using the old reliable
, etc…
I have a dialog callback that gets that Mask Object. The problem is the Mask Object it gives you gives parameters for the Mask BEFORE it was opened, and does not include changes that you have made to the mask since opening the simulink GUI. (i.e. My dialog callback is working with old data).
My Fix: ??, go back to old reliable.
I agree that the disparity between these two values is odd. I might consider it as a feature and explain it as follows.
returns the values from the dialog for the mask even if they have not been “applied”
returns the mask parameters that are being used by the block.
I’ve noticed this as well. I find it unhelpful as a developer. It can be useful to know if a bug exists and/or has been fixed in a particular version. This way one can apply workarounds if needed in code used by people who may be running many different versions of Matlab.
For example, Matlab 7.14 (R2012a), 7.13 (R2011b), and probably earlier, has a bug in the inverse complementary error function, erfcinv, where erfcinv(eps(realmin)) returns
NaN
instead of a finite real value as would be expected and as indicated by the documentation (this occurs in single precision as well). I reported this bug and suggested a simple “workaround.” The bug was acknowledged and I even suggested how it might be fixed when the engineer explained the reason for the underflow. The bug was fixed in Matlab 8.0 (R2012b), but it never showed up in the online database so you’d never know that it exists/existed.By the way, here is code that will apply a workaround in pre-R2012b versions:
Of course verLessThan only goes back to Matlab 7.4 (R2007a), but that’s as far back as I try to retain support…
[…] mind, I don’t take it personally, I simply find a workaround and move on. I’ve already posted about this before. Today I’ll discuss two additional bugs I’ve run across once-too-often, and my […]