www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 15790] New: The GC frees managed members made w/


          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 puremagic.com
          Reporter: b2.temp 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

    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);
Mar 11 2016