[Issue 15790] New: The GC frees managed members made w/ allocator.make, causing memory corruption
via Digitalmars-d-bugs
digitalmars-d-bugs at puremagic.com
Fri Mar 11 19:50:05 PST 2016
https://issues.dlang.org/show_bug.cgi?id=15790
Issue ID: 15790
Summary: The GC frees managed members made w/ allocator.make,
causing memory corruption
Product: D
Version: D2
Hardware: All
OS: All
Status: NEW
Severity: normal
Priority: P1
Component: phobos
Assignee: nobody at puremagic.com
Reporter: b2.temp at gmx.com
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.
--
More information about the Digitalmars-d-bugs
mailing list