Keep Matlab from stepping into built in functions during dbstop if error - matlab

I use dbstop error a lot when working in Matlab. A good portion of the time, a mistake causes errors to be thrown inside of built-in [m-file] functions, which then causes Matlab to stop execution and open the file. However, it's almost never helpful to debug inside of the built-in file, so this ends up disrupting my workflow. Might there be a way to set things up so that Matlab backs out of the built-in file in the debugger (never opening it), leaving me at the function call?

Although I've never found a way to tackle this problem properly, it's fairly easy to hack together a workaround:
Create a script containing something along these lines:
S = dbstack();
file_paths = cellfun(#which, {S.file}, 'UniformOutput', false);
builtins = ~cellfun('isempty', strfind(file_paths, matlabroot()));
stack_depth = find(~builtins, 1, 'first');
for ii = 1:stack_depth-1
dbup(); end
Save it somewhere that makes sense to you, and place a shortcut to it in the MATLAB toolbar.
Then, whenever this problem occurs, you just click on your little shortcut, which will automatically take you to the first non-builtin function in the debug stack.

Based on Rody's answer and feedback from Mathworks, this is the closest you can get at this point (R2016b):
S = dbstack('-completenames');
builtins = ~cellfun('isempty', strfind({S(:).file}, matlabroot()));
stack_depth = find(~builtins, 1, 'first');
hDocument = matlab.desktop.editor.findOpenDocument(S(1).file);
matlab.desktop.editor.openAndGoToLine(S(stack_depth).file,S(stack_depth).line);
hDocument.close();
if stack_depth == 2
dbup();
end
This shortcut will:
Open up the closest user function to the correct line.
Close the builtin function that opened when the error was thrown.
If the error happened only one level away from a user function, switch to that workspace.
The problem is that dbup() only works once - after the call, execution in the script stops. There's no function to switch to an arbitrary place in the stack.

Related

Seeing which part of code MatLab is currently running [duplicate]

Is there any way to stop the execution of a matlab program from the debugger like ctrl+c does, but then being able to continue execution (like you can in say c#)?
If not, is there any better way to workaround this other than trying to pre-emptively set break points or dbstop statements in your matlab code?
I would like to be able to interrupt a long running simulation to look at the current state and then continue the simulation.
The two options I'm currently using/considering are
dbstop commands (or (conditional) breakpoints) in the code.
Drawback is that sometimes I don't want to stop the simulation for a few hours, sometimes want to stop after only a few seconds (and I don't necessarily know that in advance) and this doesn't work well with this approach: If I set the break condition to break every 5 minutes, I can't leave matlab running for hours without interaction. If I set the condition to higher, I have to wait too long for the condition to hit.
include code to save the workspace every few seconds/minutes and import the workspace into a second matlab instance. Drawback is that this is a huge hassle and also doesn't necessarily allows me to resume the simulation with the state of the saved workspace then step through the code for a few iterations.
I'm hoping there is a better solution than either of the 2. Thanks for any advice!
Edit: I think what I'm going to do is write simple matlab function that checks an environment variable or a file on disk every iteration and calls dbstop if I set a flag in this file or env. This way I can control when (and if needed which of several) the breakpoint hits from outside matlab by editing the file. Messy, but should work.
This is not necessarily the best way, but you could simulate a file-based signal/interrupt framework. It could be done by checking every once in a while inside the long simulation loop for the existence of a specific file. If it does, you enter interactive mode using the keyboard command.
Something along the lines:
CHECK_EVERY = 10; %# like a polling rate
tic
i = 1; %# loop counter
while true %# long running loop
if rem(i,CHECK_EVERY) == 0 && exist('debug.txt','file')
fprintf('%f seconds since last time.\n', toc)
keyboard
tic
end
%# ... long calculations ...
i = i + 1;
end
You would run your simulation as usual. When you would like to step in the code, simply create a file debug.txt (manually that is), and the execution will halt and you get the prompt:
2.803095 seconds since last time.
K>>
You could then inspect your variables as usual... To continue, simply run return (dont forget to temporarily rename or remove the file). In order to exit, use dbquit
EDIT: Just occurred to me, instead of checking for files, an easier solution would be to use a dummy figure as the flag (as long as the figure is open, keep running).
hFig = figure; drawnow
while true
if ~ishandle(hFig)
keyboard
hFig = figure; drawnow
end
%# ...
pause(0.5)
end
With the release of R2016a, you can just hit the Pause button in the code editor and it will halt right away. The keyboard shortcut is Ctrl+F5.
To pause the execution of a program while it is running, in the Editor tab, click the Pause button. MATLAB pauses execution at the next executable line*.
When your code is running, the Start button will turn into a pause:
Another change with this release is the ability to add/remove breakpoints while running. Previously you couldn't do this, apparently.
You can set a conditional breakpoint in the MATLAB Editor. You can also use DBSTOP to do this. For example, this will set a conditional breakpoint in the file myFcn at line 20 which will stop execution when a loop variable i is a multiple of 500:
dbstop in myFcn.m at 20 if rem(i,500) == 0
Then you can continue execution after you inspect some of your variables.
If saving the workspace to a file is a good proxy for what you want, how about making a simple GUI with a toggle button. In your code, check the state of the button. If the button is depressed, save the state, update a static text to reflect time stamp of last save, unpress the button. Optionally, have a conditional breakpoint based on the state of that toggle button.
Here is an alternate solution using the waitinput File Exchange submission.
The advantage is that you can use it from whithin the current session or in cases where it is troublesome to set up a file. Also it won't leave a file behind on the computer.
The downside is there as well unfortunately, you need to wait for the checking moment before you can terminate and it costs a little bit of time.
for t = 1:10
pause(3) %Doing some calculations
str = waitinput('Enter 1 if you want to stop ',5);
if ~isnan(str)
keyboard; % Enter dbcont if you want to continue from here
end
['moving on, it is now: ' datestr(now)]
pause(3) %Doing some more calculations
end
If you want, you can prevent lines being printed to the screen. In this case you need to enter the input at the time the figure window is open (Look in your start bar on windows).
To summarize, the short code that you can put somewhere like a conditional breakpoint would be:
if ~isnan(waitinput('',5))
keyboard;
end
After certain version (I don't know which one exactly):
Windows: Ctrl + F5
Mac: Command + F5 (I guess)
Unix: I am looking for answer too
After 2016a, there is a button for that on the interface too.

Replacing Matlab title name with process Id does not work with startup.m

I want to start matlab and replace the title of matlab window to process id. So I created the following startup.m file:
cd E:\matlab_files\
jDesktop = com.mathworks.mde.desk.MLDesktop.getInstance;
jDesktop.getMainFrame.setTitle(['PID:' num2str(feature('getpid'))]);
Now, matlab changes folder to E:\matlab_files but process Id is not replaced. Once matlab has started and I execute 2nd and 3rd line of startup.m, then the title of matlab window is replaced by process id.
Please explain the cause of this behaviour.
I am using Matlab 2009b.
All of the graphics haven't finished initialising -> so you are not able to replace the title (I assume it hasn't yet been created).
You can check this by trying to disp the jDesktop.getMainFrame.getTitle to your startup.m and you will see that that is empty.
Thats the explanation as to why - you haven't asked for a fix - but I assume you want one!! ;)
You can fix this by using a timer - note I put 60 seconds in the timer below - but it could be a lot less.
function startup
if ~isdeployed % its agood practice to use this incase you ever compile your codes.
cd E:\matlab_files\
timerFcn = #updatetitle;
tfcn = timer('StartDelay', 60, 'TimerFcn', timerFcn );
start(tfcn)
end
end
function updatetitle(varargin)
jDesktop = com.mathworks.mde.desk.MLDesktop.getInstance;
jDesktop.getMainFrame.setTitle(['PID:' num2str(feature('getpid'))]);
end
I observe the same behavior. Note that startup.m is run from matlabrc.m while MATLAB is still starting up. You could experiment by putting your code in matlabrc.m, although I can't recommend editing that file.
There are a few possible reasons:
After startup.m runs, MATLAB may overwrite the title of the matlab window.
Java may not be fully available during startup, and your code clearly relies on Java.

Alternatives to `clear(function_name)` to remove function from RAM?

As stated in MATLAB's FAQ,
1.3.3.1. Why, when I edit a function file in MATLAB, is the change not seen by MATLAB until everything is cleared or MATLAB is restarted?
When you write an M-file in MATLAB, you can either write a script or a
function. The difference is that a script is read from the disk and
parsed line by line each time it is called. A function is loaded into
RAM for execution. Because it is loaded into RAM, when you edit a
function, that change is not loaded into RAM until a call to the new
function is made.
To get MATLAB to recognize your edited function, type
clear functions to clear all functions, or
clear <function name> to clear just your function out of RAM.
This is a major pain when I'm developing a function & editing it repeatedly (I use an external editor most of the time). I was thinking of putting in a final line, at least during debug, like
clear(myfunc)
but I'm concerned about unwanted side effects. Does anyone know if there are any?
Further, I'd rather have a way to configure MATLAB so it doesn't automatically store called functions in RAM once the top-level function (i.e. the one called from the console) terminates. Is that even possible?
EDIT: I should mention that MATLAB's behavior is inconsistent. Sometimes my edits take effect once I save the m-file, other times they don't even if I'm editing with the MATLAB IDE editor window.
In all honesty MATLAB has a very powerful editor so you really should
be using it. It will make you life easier. (just an opinion)
Unless you are running the code by stepping through it no change to code will be run until the code is re-run (preferably with a cleared workspace).
clear(myfunc) will clear the variables created by that function in upto that point. You can add at the end of any function or script clear variableA variableB for all variables you want cleared at the end. This will give you control to only clear what you want. Once variables are cleared the only effect will be that if those variables are called again later in the code an error will occur since they no longer exist.
If your simply testing that particular function and want to save time by not calling inputs each time and want to clear the workspace and command window at the same time. You can add the following code just beneath the function definition.
If you leave the following code and call the function from another function or script, the code will be ignored as long as the inputs are available to it externally. Anything you add to the if statement will only occur when you call the function with no inputs doc nargin. You could add it to the top level function and you would simply press the run button or f5 without having to type in the command window to run the code.
function [ output1, output2 ] = blah( input1, input2 )
if nargin == 0
clc
clear all
%above two lines will clear the workspace and command window when you run
%the function
%define function inputs
%(optionally add the following to behave as if you inserted a breakpoint
%in the location just before the error occurred (great for debugging)
db stop if error
end
*you can also add a short-cut to snippets of code up in the top right of the MATLAB interface to clear the workspace etc when they are clicked.
Hackish* idea for this:
I'd rather have a way to configure MATLAB so it doesn't automatically store called functions in RAM once the top-level function (i.e. the one called from the console) terminates. Is that even possible?
* This is the sort of thing I might use, while advising others on why it is a bad idea, also probably uses undocumented (thus unreliable) things.
Specifically if your using an external editor I guess your going to have to click on the command window to run the function...
commandWindowHandle = ...
handle(com.mathworks.mde.desk.MLDesktop.getInstance.getClient('Command Window'...
.getComponent(0).getComponent(0).getComponent(0),'CallbackProperties');
commandWindowHandle.MouseClickedCallback = 'clear functions'
It doesn't clear the function definitions on exiting a function rather on clicking on the command window
note: the callback will not fire if a function is currently running
For a potentially more reliable but more wasteful version:
commandWindowHandle.KeyPressedCallback= 'clear functions'
will help* ensure definitions are clear, but is wasteful as every keystroke will run 'clear functions'... although after one keystroke this will be quicker as there will be no functions in memory!
* No guarantee I know there are ways in which this could fail... having at least 1 keystroke in the command window after the previous function call has finished would be advisable!
To disable these set the callback to empty string ''
commandWindowHandle.MouseClickedCallback = ''
commandWindowHandle.KeyPressedCallback= ''

Running "preamble" code in MATLAB

Is there any way to make MATLAB run a certain chunk of code every time you try to run a script? For instance, I would like MATLAB to run
sprintf('Here we go...')
as soon as I hit the Run button and then move on to execute my script, so if my script were
i = 1;
i = i * i;
display(i)
I would get
ans =
Here we go...
i =
1
P.S. I would appreciate it if the people with higher reputation please corrected the title of my question for it to better reflect the content.
as soon as I hit the Run button
I am assuming you are talking about the run button in the editor. In R2012a there was a feature called "Run Configuration". A run configuration was linked to a specific script and included code to be executed prior to the script being run. There does not appear to be a global setting to be used on all function. This feature appears to have been silently removed in R2012b.
In R2013b you can chose to run a different script. Presumably you could hack the editor to get the current file and use the custom run script to run your preamble and then the current editor file. This seems like a lot of work for not much return ...
You could create a file called myrun.m
desktop = com.mathworks.mde.desk.MLDesktop.getInstance;
jEditor = desktop.getGroupContainer('Editor').getTopLevelAncestor;
title = jEditor.getTitle;
currentFilename = char(title.replaceFirst('Editor - ',''));
fprintf('Here we go...');
run(currentFilename);
and this in the editor under run Run: type code to run type myrun. One you do this once it will remember your preferences and you can then run you code via myrun with F5. It will remember your preferences across restarts.
The way to do this would be to have a preamble.m and doThis.m. In preamble.m you'd have this:
sprintf('Here we go...')
and then in doThis.m, you'd have
preamble
i = 1;
i = i * i;
display(i)
The only trick to making this work is to have them both on the path, or in the same directory.
Not sure if I got what you want, but you can divide Your m file into Code Sections. For example:
%% Section 1
sprintf('Here we go...')
%% Section 2
i = 1;
i = i * i;
display(i)
The %% is a section break. Place your cursor in the relevant section, and on the Editor tab, in the Run section, click Run Section. (or press Ctrl+Enter)
see here for more info.
If you only want this for one (or a few scripts) either add the command in the script, or make a wrapper function/shortcut.
If you want this for many scripts without input, you can create a generic wrapper:
Suppose you want to run things like myFun(a,b,c) then create a wrapper that you can call like this:
myWrapper('myFun(a,b,c)')
Then you can first call your display command and then use eval on the input of myWrapper. Note that this becomes cumbersome if your function call is multiline or contains quotes.
If these solutions can't help, you probably need to ask yourself why you are trying to do this and whether there is a better solution for the underlying problem.

Matlab clc command

I was checking the original 'clc.m' file in MATLAB. Apparently the function is written as a p-code and you just see the description which is placed in:
..\MATLAB\R2013a\toolbox\matlab\iofun\clc.m
How can I take a look at the original code?; however this is not the main question, it is just for fun.
The main point is I am looking for a way to reverse the clc process, after you clean the screen. Is there any way to reverse the clc process. The same question goes for clear all as well.
Try using home instead of clc. Whereas clc removes all text from the Command Window and moves the cursor to the top left giving you a blank window, home just moves the cursor to the top left and gives a you a blank window - but the text is still there, and you can scroll up to see it. I use home all the time rather than clc.
In either case, the text remains in the Command History window, and can be retrieved in the Command Window using the Up/Down arrows.
The reason you can't see the code behind clc is not that it's p-coded, it's that it's a built-in function (i.e. not implemented in the MATLAB language). The same is true for clear, and also many math functions such as svd, eig etc. There's no way to modify them to change what they do (such as reversing the process).
Edit: You might also like to look into the diary function, which keeps a log of all the input and output at the command window in a specified file. I have the following lines in my startup.m file (type doc startup if you don't know how to use MATLAB startup files):
diaryFolder = 'C:\diaries';
diaryFileName = ['diary', datestr(now, 'yyyymmdd'), '.txt'];
diary(fullfile(diaryFolder, diaryFileName))
So whenever I start MATLAB, it's automatically capturing all command window input and output to a diary file that's named by the date - If I start MATLAB multiple times a day, it just appends to the same file. I can clc or home whenever convenient, and there's always a record kept of everything that I can search through if necessary.
I don't believe there would be anyway to undo the clc process. That said, it is possible to still view the command history, so that might get you somewhere.
Once you clear the data, I believe it's gone forever. I highly doubt that data is stored in memory somewhere. I know that after a certain number of lines, the history is deleted. So your best bet is to start figuring out how large that buffer is and proceed from there to see if you can find anything interesting.