Thread overview | |||||||||
---|---|---|---|---|---|---|---|---|---|
|
April 04, 2016 Possible bug in RVO? | ||||
---|---|---|---|---|
| ||||
I have encountered a weird bug. I defined a Set class, which has a opBinary!"-". And somehow this: auto tmp = set_a-set_b; produces different results as this: set_a = set_a-set_b; the latter will produce an empty set. I tried to reduce the source code to get a test case. But this problem just goes away after removing some code. Any ideas what I could have done wrong? |
April 04, 2016 Re: Possible bug in RVO? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Yuxuan Shui | On Monday, 4 April 2016 at 03:28:01 UTC, Yuxuan Shui wrote:
> I have encountered a weird bug.
>
> I defined a Set class, which has a opBinary!"-". And somehow this:
>
> auto tmp = set_a-set_b;
>
> produces different results as this:
>
> set_a = set_a-set_b;
>
> the latter will produce an empty set.
>
> I tried to reduce the source code to get a test case. But this problem just goes away after removing some code.
>
> Any ideas what I could have done wrong?
OK, I think I got a test case:
import std.traits;
struct Set {
public:
void insert(ulong v) {
aa[v] = true;
}
size_t size() const {
return aa.length;
}
auto opBinary(string op)(ref Set o) const {
Set ret;
foreach(k; aa.byKey)
if (k !in o.aa)
ret.insert(k);
return ret;
}
@disable this(this);
bool[ulong] aa;
}
struct XX {
Set a, b, tmp;
this(int n) {
a.insert(n);
tmp = a-b;
a = a-b;
}
}
void main(){
import std.stdio;
XX xx = XX(1000);
writeln(xx.a.size);
writeln(xx.tmp.size);
}
This does not happen when 'a' is on stack, that's why I was having trouble reproducing it.
I don't think this is valid code, because Set has disabled post-blit, 'a = a-b' should report an error. However, I don't think current behavior of dmd is correct either.
|
April 04, 2016 Re: Possible bug in RVO? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Yuxuan Shui | On Monday, 4 April 2016 at 03:28:01 UTC, Yuxuan Shui wrote:
> I have encountered a weird bug.
>
> I defined a Set class, which has a opBinary!"-". And somehow this:
>
> auto tmp = set_a-set_b;
>
> produces different results as this:
>
> set_a = set_a-set_b;
>
> the latter will produce an empty set.
>
> I tried to reduce the source code to get a test case. But this problem just goes away after removing some code.
>
> Any ideas what I could have done wrong?
A slightly more reduced test case:
struct Set {
void insert(ulong v) {
aa[v] = true;
}
@disable this(this);
bool[ulong] aa;
}
auto clobber(ref Set x, ref Set o) {
Set ret;
ret.aa = x.aa;
return ret;
}
struct XX {
Set a, b, tmp;
this(int n) {
a.insert(1);
//a.aa[1] = true; <--- Swap above line with this doesn't trigger the bug
tmp = a.clobber(b);
a = a.clobber(b);
}
}
void main(){
import std.stdio;
XX xx = XX(0);
writeln(xx.a.aa.length);
writeln(xx.tmp.aa.length);
}
|
April 04, 2016 Re: Possible bug in RVO? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Yuxuan Shui | On Monday, 4 April 2016 at 03:55:26 UTC, Yuxuan Shui wrote:
> On Monday, 4 April 2016 at 03:28:01 UTC, Yuxuan Shui wrote:
>> I have encountered a weird bug.
>>
>> I defined a Set class, which has a opBinary!"-". And somehow this:
>>
>> auto tmp = set_a-set_b;
>>
>> produces different results as this:
>>
>> set_a = set_a-set_b;
>>
>> the latter will produce an empty set.
>>
>> I tried to reduce the source code to get a test case. But this problem just goes away after removing some code.
>>
>> Any ideas what I could have done wrong?
>
> A slightly more reduced test case:
>
And LDC has the same problem with the first test case, but not with the second one.
|
April 04, 2016 Re: Possible bug in RVO? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Yuxuan Shui | On Monday, 4 April 2016 at 03:55:26 UTC, Yuxuan Shui wrote: > On Monday, 4 April 2016 at 03:28:01 UTC, Yuxuan Shui wrote: > auto clobber(ref Set x, ref Set o) { > Set ret; > ret.aa = x.aa; assert(x.aa.length > 0); // <-- boom > return ret; > } No idea myself but that's where it seems to go wrong. |
April 04, 2016 Re: Possible bug in RVO? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Anonymouse | On 04/04/2016 09:36 AM, Anonymouse wrote:
> On Monday, 4 April 2016 at 03:55:26 UTC, Yuxuan Shui wrote:
>> On Monday, 4 April 2016 at 03:28:01 UTC, Yuxuan Shui wrote:
>> auto clobber(ref Set x, ref Set o) {
>> Set ret;
>> ret.aa = x.aa;
> assert(x.aa.length > 0); // <-- boom
>> return ret;
>> }
>
> No idea myself but that's where it seems to go wrong.
Looks like a bug. Just to make it more visible:
auto clobber(ref Set x, ref Set o) {
writefln("entered clobber - x.aa: %s", x.aa);
Set ret;
writefln("did not touch x.aa - x.aa: %s", x.aa);
ret.aa = x.aa;
return ret;
}
x.aa changes during the second call:
entered clobber - x.aa: [1:true]
did not touch x.aa - x.aa: [1:true]
entered clobber - x.aa: [1:true]
did not touch x.aa - x.aa: [] <-- What happened?
Ali
|
April 05, 2016 Re: Possible bug in RVO? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Monday, 4 April 2016 at 21:31:08 UTC, Ali Çehreli wrote: > On 04/04/2016 09:36 AM, Anonymouse wrote: >> On Monday, 4 April 2016 at 03:55:26 UTC, Yuxuan Shui wrote: >>> [...] >> assert(x.aa.length > 0); // <-- boom >>> [...] >> >> No idea myself but that's where it seems to go wrong. > > Looks like a bug. Just to make it more visible: > > auto clobber(ref Set x, ref Set o) { > writefln("entered clobber - x.aa: %s", x.aa); > Set ret; > writefln("did not touch x.aa - x.aa: %s", x.aa); > ret.aa = x.aa; > return ret; > } > > x.aa changes during the second call: > > entered clobber - x.aa: [1:true] > did not touch x.aa - x.aa: [1:true] > entered clobber - x.aa: [1:true] > did not touch x.aa - x.aa: [] <-- What happened? > > Ali I filed an bug report here: https://issues.dlang.org/show_bug.cgi?id=15869 |
Copyright © 1999-2021 by the D Language Foundation