bug in assigning to dynamic array element

ketmar via Digitalmars-d digitalmars-d at puremagic.com
Sat Nov 1 02:03:18 PDT 2014


Hello.

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.


as i can guess, 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 it is stored in the invalid address. 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 like 'mk2' asserts,
which proves that 'mk1' was really executed.


this stinky thing took me two days to find, 'cause it was in a bigger
codebase, and i was searching for the bug in my code. the bug
mysteriously disappearing when i inserting debug printing ('cause i
assigned `saveIt()` result to variable to print it) didn't much help
either. ;-)

the bug is reproducible with gdc and dmd head on x86, without
optimisations turned on.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: not available
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20141101/81ea1f1f/attachment.sig>


More information about the Digitalmars-d mailing list