Have you ever wanted MATLAB to pause in debug mode when a certain condition is met? Perhaps when a specific problem-file out of a directory is read or on an iteration of a for-loop that yields an unexpected result? Perhaps that for-loop has to iterate a few dozen or hundred times before the problem iteration occurs and you don't want to walk through step by step in debug mode?
In this post, we're going to survey a few different ways to handle this.
I was talking with a MATLAB user recently about the merits of the keyboard function of which I'm not a big fan. Keyboard pulls you into debug mode as soon as it's encountered. They claimed to like it for difficult debugging when certain criteria are met.
Here's a simple example scenario. CM is the cameraman image:
This is a simple algorithm to show how many pixels are brighter than each pixel value in the uint8 range of [0 255].
xg = zeros(1, 256); for ii = 0:255 xg(ii+1) = sum(CM(:)>ii); end plot(0:255, xg) ylabel('Pixels Greater Than X') axis tight
Somewhere around iteration 125 appears to be giving me problems; I'd expect the curve to be positive through to 255.
I want to see what's happening on iteration 125 and the subsequent ones. One way would be to put a break point on the calculation line, hit run, and then hit the continue button 125 times hoping I don't get in a rhythm and accidentally skip it. This has some obvious shortcomings in that it doesn't scale and is time consuming.
The approach with keyboard would look like this:
xg = zeros(1, 256); for ii = 0:255 if ii == 125 keyboard end end
Now on the 125th iteration, we enter the if-statement and can step in debug mode into the problem area. This is pretty straight-forward and is a safe, decent solution. However, it requires changing the code in order to debug it and will require changing it again once we've fixed the bug.
These breakpoints can be set from the breakpoints menu on the editor tab or with dbstop directly. Here's the same code encapsulated in a function called badForLoop.
function badForLoop(CM) xg = zeros(1, 256); for ii = 0:255 xg(ii+1) = sum(CM(:)>ii); end plot(0:255, xg) ylabel('Pixels Greater Than X') axis tight end
To set it from the breakpoints menu, select "Set Condition" while the cursor is on the line you'd like to stop on.
Then enter your condition; any valid MATLAB code will work here.
To set the same breakpoint programmatically:
dbstop in badForLoop at 4 if (ii==125)
If you think you have a fix, you can then disable the breakpoint without clearing it by either clicking on the yellow breakpoint itself (an X will appear over it indicating it's disabled). If the problem is resolved, clicking the breakpoint again will clear it or you can reenable it by right clicking. This can be done from the menu as well and clearing can be done with dbclear.
The analogous workflow with keyboard would be to highlight the selection and comment it out to "disable" and then delete to clear.
The fix for this toy problem was that the image was stored as an int8 with a range [-128 127] rather than a uint8 with range [0 255].
Additionally, dbstop has some predefined conditions to stop on including on errors, warnings, or if nans or infs are encountered. If you haven't discovered dbstop if error yet, I strongly suggest giving it a try. When an error occurs, it stops and you can view the state of the world as it was when the error occurred.
Do you have any debugging war stories where one of these tricks could've helped? What about other uses for the keyboard command? Let us know here.
To leave a comment, please click here to sign in to your MathWorks Account or create a new one.