Create MException object with a custom non-empty stack (without actually throwing it)
6 vues (au cours des 30 derniers jours)
Afficher commentaires plus anciens
Dear Matlab Community,
Is it possible to create a valid MException object with a non-empty stack without actually throwing it?
The goal is to execute something somewhere in the code hierarchy and collect the occuring errors with a purpose to process them later in the top-level GUI code, e.g.
function errs = myMethod( this, args )
errs = MException.empty();
% ... do some safe stuff ...
try % ... do some unsafe stuff ...
catch err, errs = [ errs; err ];
% ... do some cleanup ...
return;
end
% ... do more safe stuff ...
try % ... do more unsafe stuff ...
catch err, errs = [ errs; err ];
% ... do some cleanup ...
return;
end
% continue
end
In the example above, the ERR output value will be either an empty array of MExceptions (i.e. no errors), or a scalar MException including the complete stack of the error location, or a vector of such. The actual code may have more hierarchy levels, i.e.
function errs = myMethod( this, args )
someErrs = this.doSomeStuff( someArgs );
moreErrs = this.doMoreStuff( moreArgs );
restErrs = this.doRestStuff( restArgs );
errs = [ someErrs; moreErrs; restErrs ];
end
... where each called submethod or function has similar ERRS output, which are collected to a single vector in the top-level code.
My question is, whether this is possible to locally create a custom MException with a complete local or custom stack without actually throwing it, e.g.:
% ... do some safe stuff ...
if ( someErrorCondition )
% do specific cleanup
% create an exception, but don't throw it, just collect
err = MException( 'myFunc:myErr', 'my error message', dbstack() );
errs = [ errs; err ];
end
% ... do more safe stuff ...
Unfortunately, the syntax above will not work (third "stack" argument is not supported), the stack field of MException is only set by throwing it, and is read-only for an existing MException.
The only way to create an MException object with a custom non-empty stack is seemingly to actually manually throw an exception using error( errStruct ) syntax:
% ... do some safe stuff ...
if ( someErrorCondition )
% do specific cleanup
% create an error specification structure with a custom stack
err = struct( 'identifier', 'myFunc:myErrr', 'message', 'my error message', 'stack', dbstack() );
% throw an exception and catch it immediately,
% then it will have a non-empty user-defined stack
try error( err ); catch err; end
% collect an exception
errs = [ errs; err ];
end
% ... do more safe stuff ...
The latter way works, but seems to be rather ugly and possibly includes a significant overhead to throw-and-catch an error, especially if this happens multiple times for multiple errors.
A possible solution would be to collect the errors as a cell array instead of an array of MExceptions. This would allow using some alternative error format, but would also require a dedicated error-format-dependent error processing code at the top-level, and this is what I would prefer to avoid as long as there's a way to use the native MExceptions.
So,
– is there a way to create an MException object with a custom stack, or
– is there some typical alternative approach for such multiple error handling?
Thanks in advance!
0 commentaires
Réponses (1)
Steven Lord
le 21 Avr 2022
Preallocate a cell array.
M = cell(1, 3);
Run the code that may throw an error. If it does, catch the error in the appropriate element of the cell array. I'll do this three times, where the first and third do error and the second does not.
try
x = [1 2] + [1 2 3]; % Error, can't add a 1-by-2 and a 1-by-3
catch ME
M{1} = ME;
end
try
q = 1:10; % Does not error
catch ME
M{2} = ME;
end
try
y = [1 2; 3 4]*magic(3); % Error, can't multiply a 2-by-2 and a 3-by-3
catch ME
M{3} = ME;
end
Let's look at the cell array. The first and third cells are non-empty, the second is empty.
celldisp(M)
When we concatenate the three cells together using a comma-separated list the empty cell basically disappears, leaving us our two errors.
theErrors = [M{:}]
The first is M{1} and the second is M{3}.
isequal(theErrors(1), M{1})
isequal(theErrors(2), M{3})
Is theErrors the MException array that you were hoping to create?
1 commentaire
Voir également
Catégories
En savoir plus sur Error Handling dans Help Center et File Exchange
Produits
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!