Bug 15790 – The GC frees managed members made w/ allocator.make, causing memory corruption
Status
RESOLVED
Resolution
DUPLICATE
Severity
normal
Priority
P1
Component
phobos
Product
D
Version
D2
Platform
All
OS
All
Creation time
2016-03-12T03:50:00Z
Last change time
2016-12-27T11:36:10Z
Assigned to
nobody
Creator
b2.temp
Comments
Comment #0 by b2.temp — 2016-03-12T03:50:05Z
The managed members of an aggregate instanciated with std.experimental.allocator can be freed during a GC pass, and even if the allocator used is not GCAllocator.
The following program illustrates the issue:
import core.memory;
import std.experimental.allocator.mallocator;
import std.experimental.allocator.common;
enum fill = "azertyuiopqsdfghjklm";
auto make(T, Allocator, A...)(auto ref Allocator alloc, auto ref A args)
{
import std.algorithm : max;
import std.conv : emplace;
auto m = alloc.allocate(max(stateSize!T, 1));
version(none) GC.addRange(m.ptr, m.length); // activate this to fix the error
if (!m.ptr) return null;
scope(failure) alloc.deallocate(m);
static if (is(T == class)) return emplace!T(m, args);
else return emplace(cast(T*) m.ptr, args);
}
struct Node
{
this(string c){content = c;}
string content;
Node*[] nodes;
}
void main()
{
Node* root = make!Node(Mallocator.instance, fill);
foreach(immutable i; 0 .. 10000)
{
root.nodes ~= make!Node(Mallocator.instance, fill);
foreach(immutable j; 0 .. 100)
root.nodes[i].nodes ~= make!Node(Mallocator.instance, fill);
}
assert(root.content == fill);
foreach(immutable i; 0 .. root.nodes.length)
{
assert(root.nodes[i].content == fill);
foreach(immutable j; 0 .. root.nodes[i].nodes.length)
assert(root.nodes[i].nodes[j].content == fill);
}
}
Because "content" is a managed type, it's corrupted during a GC pass.
While the tree structure is OK, checking the content reveals the corruption (.ptr or .length or both points to invalid mem location). When the LOC that declares the aggregate to the GC is activated, the error disapears.
Either make() documentation should explicitly warn about this or a template parameter could indicate if the content of the aggregate has to be declared to the GC.
Comment #1 by greeenify — 2016-12-27T11:36:10Z
*** This issue has been marked as a duplicate of issue 16982 ***