Loren on the Art of MATLAB

April 30th, 2007

A Little Bit on Message Handling

This is a quick note about handling errors and warnings in MATLAB. In particular, the function error has a couple of aspects that people sometimes trip over or overlook.

Contents

What error Does

The main thing error is responsible for is issuing a message to the user that he or she has done something incorrectly. The first place you might see error checking in a function is looking at the input arguments. Using nargchk is a common way to see if there's a problem and then calling error afterwards.

Sample Snippet

Let's see one pattern. Here we are checking that the number of inputs, narg, lies between 2 and 7. If not, we'll issue an error.

narg = 4;
msg = nargchk(2,7,narg,'struct');
if ~isempty(msg)
    error(msg)
end

It turns out, this code is more complex than necessary. We can equivalently write

error(nargchk(2,7,narg,'struct'));

because the function error does not produce an error with empty input. This is a gotcha that people occasionally run into. You can't just use a simple statement like error('') to signal an error in your code.

Why Use the 'struct' Option?

I am using the 'struct' argument for nargchk so the output is a structure with both a message identifier and the message itself. Why? Because I, as the application developer, could choose to issue a different message or take a different action, e.g., using a try-catch construct. Using message identifiers for warning users about something allows the users to control that specific warning. Perhaps, after seeing it once, a user might want to turn that warning off, but would still like to be alerted of other possible issues.

Another gotcha

Users are also occasionally tripped by turning a particular warning off, running some other code, and then not expecting to see the turned off warning showing up when they use lastwarn to see if something has happened. Depending on the sequence of events, it's possible that lastwarn will return a message from a warning that was turned off. warning off ID simply turns off the display of the warning message.

Any More Message Wisdom?

If you have more message wisdom, post your thoughts here.


Get the MATLAB code

Published with MATLAB® 7.4

10 Responses to “A Little Bit on Message Handling”

  1. F Vinci replied on :

    I seek more message wisdom… Specifically, I’d like to get
    the variable list of arguments passed into a given function
    as a string, to simplify finding/fixing problems in a large application that writes out cascades of files to disk…

    Putting it another way, how do I access the arguments of a function call in matlab as a string, without knowing a priori the type/number of the parameters ? I’d like to record in a file the calling argv (argument vector) for every function call, so that I can try to find problems with some optimization results, where things diverge long after some function was called with erroneous values…

    dbstack returns a structure that *almost* has what I need…

    I hope someone reading this blog can make me a size matlab programmer!

  2. Loren replied on :

    F Vinci-

    It would be nice if MATLAB had a more natural way for you to find out the argument list. For now, you can try this:

    dbtype yourfunction 1

    will show you the first line of the M-file. If it’s the usual function line, you can see the argument list there.

    –Loren

  3. Ken replied on :

    F Vinci-

    It sounds to me like you want to know what args were used by the caller, but from inside the called function. If so, you can use inputname, a built-in matlab function, inside the calling function.

    -Ken

  4. F Vinci replied on :

    Thanks for the replies/comments.

    Ken, you are right, this is what I want. In essence I’d like
    to write out to a file the calling parameters of a function,
    from within the function itself.

    Ken’s suggestion is a good one, I checked inputname, and it
    “almost” does what I want… The problem is that I get the
    name of the variable in the caller’s space, and if it’s an
    evaluated expression I get nothing at all.

    What I’d really really like would be the evaluated arguments that the function got when it was called…
    I think i can explain that as a kind of “stack trace”.
    For example, if I use,

    function myplot(x,varargin)
    plot(x,varargin{:})
    magic_argument_printing_to_file_command;
    return

    then when I call myplot as,

    myplot(sin(0:.1:1),’color’,[.5 .7 .3],’linestyle’,':’)

    I’d like to see this written out to a file,
    calling parameters for function MYPLOT =>
    sin(0:.1:1)
    ‘color’
    [.5 .7 .3]
    ‘linestyle’
    ‘:’
    Now, assuming that sin(0:.1:1) has already been evaluated within myplot(), i still would find it useful to have the
    actual vector written to the file, so that I could recompute all function calls a posteriori…

    Loren’s suggestion is interesting, but won’t help me here, I think.

    Thanks for any suggestion!

  5. Ljubomir Josifovski replied on :

    Is there maybe a way to make the warning function (maybe even error functions?) map their action(s) onto throw and so enable the caller to catch them? I run into this in the context of try, rmpath(’may not exist’); catch … which does not work (ie the program stops if “dbstop if warning” because rmpath warns if the path to be removed is not in the path) because try/catch/throw is unrelated to error/warning functions. I guess I’d like if rmpath worked the way “load” works - example: “try, q=load(’qwe’); disp(’Worked’); catch disp(’Failed’); end”. Thanks in advance.

  6. Loren replied on :

    Ljubomir-

    There is no analogous try-catch way to catch a warning. You would need to interrogate using the lastwarn function just after you issue the command that might warn.

    –Loren

  7. Ken F replied on :

    I have a question about the error function. What I would like to do is to display an error message, without displaying any of the stack information. I want this because I am making an object class, and I don’t want the users to be able to see which functions are throwing the errors.

    What I have tried to do was:

    (start of code snippet)

    switch error_type
    case 1
    error_text=’??? Some error text’;
    case 2
    error_text=’??? Some error text’;

    end

    %Make the error structure that will be displayed.
    serror=struct(’message’, error_text, ‘identifier’, ”,…
    ’stack’, struct(’file’, ”, ‘name’, ‘Standard Structure’, ‘line’, 1));

    %Throw the actual error.
    error(serror);

    (end of code snippet)

    On my computer at work, the code does what I want it to do. But, when I try it at home, the stack information is still being displayed when I use the error function.

    Is there some kind of setting that needs to be set?

    I’ve even tried:

    dbstack=struct(’file’, ”, ‘name’, ‘Standard Structure’, ‘line’, 1);

    serror=struct(’message’, error_text, ‘identifier’, ”,…
    ’stack’, dbstack);

    but I get the same problem.

    Any ideas?

  8. Loren replied on :

    Ken-

    I would recommend reading up on MExceptions (which weren’t available when I wrote this post). Also, check out throw (and maybe rethrow or throwAsCaller) which allows some control of the stack.

    –Loren

  9. steven replied on :

    I am having issues with throwAsCaller when
    dbstop if error
    is engaged. When the error is thrown, the debugger stops in the code which issues the throwAsCaller, and *not* in the caller, which is what I want.
    From the online help for throwAsCaller:
    “In some cases, it is not relevant to show the person running your program the true location that generated an exception, but is better to point to the calling function where the problem really lies…”
    This is exactly what I want to do, but dbstop does not do the right thing. I have tried a number of variations, including using ‘evalin’ to evaluate the error in the caller, etc, but to no avail.

    Is there any way to do this? to cause an error to occur in the caller?

    thanks much,

  10. Loren replied on :

    Steven-

    There is no really good way to do this now. I will enter an enhancement request.

    –Loren

Leave a Reply

Wrap code fragments inside <pre> tags, like this:

<pre class="code">
a = magic(3);
sum(a)
</pre>

If you have a "<" character in your code, either follow it with a space or replace it with "&lt;" (including the semicolon).


Loren Shure works on design of the MATLAB language at The MathWorks. She writes here about once a week on MATLAB programming and related topics.

  • Jun: I totally can not believe it, Loren. You are really helpful. Thank you so much, MATLAB master!
  • Loren: Wow folks- Always lots of interest when there’s a quickie to try out! I will only make 2 general...
  • Loren: Jun- ismember is your friend here: >> [aa,ind] = ismember(Array2,Arra y1) aa = 1 1 1 1 1 1 1 ind = 1 2 1 4 4 3...
  • Dan: I like the first way better than the second way. Combining the arrays into one and running any is nice, although...
  • James Myatt: How about I = (a == 0 | b == 0); a(I) = []; b(I) = [];
  • Tunc: Hello Loren, love your blog because of such inspiring and challenging comments to such ’small’...
  • Pekka Kumpulainen: Here is my tradeoff. I usually want to keep the original variables as they are most probably...
  • Iain: Followup: Of course, to allow NaNs (counting them as non-zero): mask = (a~=0) & (b~=0); The mask says “a...
  • Matt Fig: I would usually go with something like this: y = a&b; x = a(y); y = b(y); But I was surprised to find...
  • kk: c=all([a;b]) a(c) a(b)

These postings are the author's and don't necessarily represent the opinions of The MathWorks.