On Thursday, 13 May 2021 at 19:48:44 UTC, Ali Çehreli wrote:
I was writing this example that shows a use case for the
problem (marked with BUG below):
```D
struct Fraction {
auto n = 0L;
auto d = 1L;
// ... other bits ...
ref Fraction reduce() {
import std.numeric : gcd;
// v = gcd(n, d);
// if (v > 1) {
// n /= v;
// d /= v;
// }
return this;
}
// ... etc ...
}
ref foo() {
import std.stdio : writeln;
auto f = Fraction(3, 9);
// BUG: Returns reference to an object on the stack
return f.reduce();
}
void main() {
// Refers to a temporary (it would be a copy without the &)
auto f = &foo();
// Do some unrelated things hoping that space for dead
objects on
// the stack will be reused.
import std.stdio;
import std.random;
writeln("doing something else: ", uniform(0, 6));
writeln(f.d); // Access dead and overwritten object (does NOT
print
// 9 on my system)
}
```
Putting 'return' where Steve shows makes the compiler guard us
against this misuse and the program thankfully does not compile.
Ali
Hi thank you both for your answers. I had understood from an
earlier chapter how this could introduce a bug, but I was
confused because the warning suggests attaching ```return``` to
the parameter, which is empty in the declaration.
So my next question would be how come ref based operator
overloads are not labelled as return and do not show this warning?
``` D
struct Fraction {
auto n = 0L;
auto d = 1L;
ref Fraction opUnary(string op)()
if (op == "++") {
n += d;
return this;
}
}
ref Fraction foo() {
auto f = Fraction(1, 3);
// Same bug as with reduce
return ++f;
}
```