Bug 13642 – std.container.Array: change of length reallocates without notifying GC
Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P1
Component
phobos
Product
D
Version
D2
Platform
All
OS
All
Creation time
2014-10-21T06:10:43Z
Last change time
2018-03-05T17:58:22Z
Assigned to
No Owner
Creator
thedeemon
Comments
Comment #0 by dlang — 2014-10-21T06:10:43Z
The Array.Payload.length setter calls realloc() when length increases, but doesn't call GC.removeRange and GC.addRange. When data in the array contains pointers to some managed objects, GC may collect those objects and now we have dangling pointers in the array, which later causes Access Violations.
The following program crashes on 2.066:
module main;
import std.stdio, std.container.array, core.memory;
class C { void hi() { writeln("hi"); } }
void main(string[] argv) {
Array!C arr;
enum N = 10;
//arr.reserve(N); // uncomment this and it will work fine
arr.length = N;
foreach(ref x; arr) x = new C; // create N objects
GC.collect(); // do a GC
arr[1].hi(); // now this object is dead!
}
Comment #1 by safety0ff.bugz — 2014-10-21T08:37:29Z
Right, the realloc in length(size_t) should be replaced with similar code to reserve, i.e.:
static if (hasIndirections!T)
// use malloc/copy/free along with GC.addRange & GC.removeRange
else
// use realloc
Comment #2 by github-bugzilla — 2018-03-05T17:58:21Z