November 01, 2014 [Issue 13670] New: bug in assigning to dynamic array element | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=13670 Issue ID: 13670 Summary: bug in assigning to dynamic array element Product: D Version: D2 Hardware: x86 OS: Linux Status: NEW Severity: critical Priority: P1 Component: DMD Assignee: nobody@puremagic.com Reporter: ketmar@ketmar.no-ip.org let's run this code: struct Info { size_t[] list; } size_t saveIt (ref Info info, size_t count) { if (count < 1) return 666; size_t idx = info.list.length; info.list.length = idx+count; foreach (; 0..count) { info.list[idx] = saveIt(info, count-1); //!!! assert(info.list[idx] != 0); ++idx; } return 666; } void main () { auto info = Info(); saveIt(info, 2); } it should work, but it asserts. the fault line is marked by '!!!'. if i'll change it to this: auto n = saveIt(info, count-1); info.list[idx] = n; everything works ok. i'm guessing that the bug is in evaluating left part of '=' operation before the right part. assignment using the old array data address, but the array was resized, so the old address is invalid. to prove that, let's change the code a little: size_t saveIt (ref Info info, size_t count) { if (count < 1) return 666; size_t idx = info.list.length; info.list.length = idx+count; foreach (; 0..count) { auto p0 = &info.list[idx]; info.list[idx] = saveIt(info, count-1); auto p1 = &info.list[idx]; if (info.list[idx] == 0) { assert(*p0 != 0); //mk1 assert(*p1 != 0); //mk2 } assert(info.list[idx] != 0); ++idx; } return 666; } line with 'mk1' should assert, but it doesn't! and line with 'mk2' asserts, which proves that 'mk1' was really executed. the bug is reproducible with gdc and dmd head on x86, without optimisations turned on. -- |
Copyright © 1999-2021 by the D Language Foundation