On Friday, 5 June 2020 at 21:20:09 UTC, Steven Schveighoffer wrote:
This kind of sounds like a codegen bug, a race condition, or (worst case) memory corruption.

I think it must have been memory corruption: I had not realized that our old Pascal compiler aligns struct members on one byte boundaries, and also uses ubyte as the base type for enumerations (or ushort if required) instead of uint. When using memory mapped files this binary incompatibility likely caused the corruption.

But, after correcting that mistake, suddenly things broke that had been working for a long time. Having no idea what could be wrong this time, I spent quite some time dustmiting (thanks Vladimir!) and manually reducing the code. VoilĂ :


import std.stdio;
import core.memory;

struct Nothing
{
}

struct Info
{
align(1):
  ubyte u;
  Nothing*[2] arr;
}

Info* info;

void main()
{
  info = new Info;
  writeln("1");
  GC.collect();
  info.arr[0] = new Nothing;
  writeln("2");
  GC.collect();
  info.arr[1] = new Nothing;
  writeln("info.arr[0]  = ", info.arr[0]);
  writeln("info.arr[1]  = ", info.arr[1]);
assert(info.arr[0] != info.arr[1], "Live object was collected!");
}


(The assert triggers on Windows, not on run.dlang.org.) Unfortunately for me, I cannot blame this on the compiler. It violates the requirements from the spec:

"Do not misalign pointers if those pointers may point into the GC heap" (https://dlang.org/spec/garbage.html)

I am glad to have found the cause of the breakage finally, but it won't be easy to find a generic solution...

-Bastiaan.

Reply via email to