Crash when overloading returns custom class

Here is a minimum working example of my problem. It consists of two files in two directories, like this:
...
myClass.m
@double (this is a directory)
mtimes.m
I have defined a new class called myClass. Calling myClass(a, b), with a and b being doubles, returns a myClass object, with a 'num' and a 'str' propery. Both properties are just the product a*b, as a double and written as a string. Here is the code, saved in myClass.m:
classdef myClass
properties
num
str
end
methods
function c = myClass(a, b)
res = a * b;
c.num = res;
c.str = num2str(res);
end
end
end
I want to call myClass every time I try to multiply a double with a char. For this, I have the following code in the file called mtimes.m in a directory @double:
function c = mtimes(a, b)
if isa(a, 'double') && isa(b, 'char')
c = myClass(a, str2double(b));
else
% Normal double*double multiplication:
c = builtin('mtimes', a, b);
end
end
Now, myClass(3, 5) and 3*'5' are exactly equivalent (the same is true for any other pair of numbers). In the command window, everything works perfectly. I can run 3*'5' as well as x = 3*'5'. If I now create an m-file in the same directory as myClass.m and run 3*'5' from this file, it works the same. But when I assign it to a variable, x = 3*'5', Matlab crashes with a large error message.
Incidentally, if I do the same thing with a standard class instead of a custom written one, no error occurs.
What is the problem here? How can it be solved? And how come that the behavior of code inside an m-file is different from that of direct input into the command window?
If anyone can solve this, I would be very grateful!

Antworten (1)

Matt J
Matt J am 24 Feb. 2013
Bearbeitet: Matt J am 24 Feb. 2013

1 Stimme

I'm just guessing, but it might be that the behavior is different inside an mfile because of the JIT. The syntax you use to generate x=3*'5' leaves no hints that the outcome will be other than double. The only way to determine the class of the result is to execute 3*'5' first. If the JIT tries to circumvent that mechanism in the interest of speed and predicts ahead of time that 3*'5' will yield the usual double result, then when you end up assigning to x a non-double data type, I can see it creating a segmentation fault.

4 Kommentare

Matt J
Matt J am 24 Feb. 2013
Bearbeitet: Matt J am 24 Feb. 2013
By the way, it appears that you've been way too persistent with this approach, ignoring many previous recommendations not to do this, e.g.,
Why is it worth all this pain? It seems unnecessarily complicated and dangerous to hack the native @double/mtimes method. As I advised you in one of those threads, why not create your own myChar class if you want new behavior for the char class? You're already using a user-defined class anyway.
Jeppe
Jeppe am 24 Feb. 2013
Thanks for the response.
I have understood that what I'm trying to do is "dangerous". I'm quite sure though, that in the final implementation, it's safe. It is wort "all the pain" because I like the syntax 3*'5' much more than myClass(3, 5), in the real situation.
I have tried disabling JIT, but the result is the same. Also, if I set myClass to return a char or a uint or a cell or any other built-in data type, no problem occurs.
I can even use x = mtimes(3, '5') inside m-files. It is only the operator form x = 3*'5' which does not work.
I do not understand what you mean by creating my own myChar class. What should this class be like? How should I use it?
Matt J
Matt J am 24 Feb. 2013
Bearbeitet: Matt J am 25 Feb. 2013
I'm quite sure though, that in the final implementation, it's safe.
There's no real basis for your certainty. If you could be sure that there's a way to get it to work, you would be able to fix the segmentation faults yourself.
I do not understand what you mean by creating my own myChar class. What should this class be like? How should I use it?
Below is a classdef something along the lines of what Cedric advised you in a previous post, except that I allow you to define a unit to have weight 1 by default. Notice from my examples that once you've constructed once instance of a given measurement unit, you can use exactly the simple multiplicative syntax that you've been aiming for.
>> kg=myclass('kg'); %a unit of kilograms
>> x=3*kg
x =
3 kg
>> y=4*x
y =
12 kg
classdef myclass
properties
num=1;
units
end
methods
function c = myclass(units, num)
c.units = units;
if nargin>1,
c.num=num;
end
end
function c=mtimes(num,obj_myclass)
c= obj_myclass;
c.num = num*c.num;
end
function display(obj)
disp ' '
disp([inputname(1) ' = '])
disp ' '
disp([' ' num2str(obj.num) ' ' obj.units]);
disp ' '
end
end
end
"all the pain" is likely to be close to infinity in that case. Matt's suggestion is to use a custom class for one of the operands in the product, so you can catch the operation with a simple overload, e.g.
x = 3 * myChar(5)
or
x = 3 * myChar('28')
In these expressions, ntimes() can be overloaded in myChar so you don't have to mess up with double.ntimes().

Melden Sie sich an, um zu kommentieren.

Produkte

Gefragt:

am 24 Feb. 2013

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by