GC being too eager?

Steven Schveighoffer schveiguy at yahoo.com
Fri Apr 11 05:26:16 PDT 2014


On Fri, 11 Apr 2014 07:25:15 -0400, Paulo Pinto <pjmlp at progtools.org>  
wrote:

> On Friday, 11 April 2014 at 09:32:29 UTC, Chris wrote:
>> On Friday, 11 April 2014 at 06:51:01 UTC, Paulo Pinto wrote:
>>> On Thursday, 10 April 2014 at 09:31:30 UTC, John Colvin wrote:
>>>> On Thursday, 10 April 2014 at 09:24:51 UTC, Paulo Pinto wrote:
>>>>> In a toy project I am working on with D v2.065, I came to the  
>>>>> following situation:
>>>>>
>>>>> Node path = solver.find (map, start, end);
>>>>> if (path !is null) {
>>>>>  path.writeContents();  <-- Access Violation
>>>>> }
>>>>>
>>>>> Apparently between the test and trying to use the class, the  
>>>>> reference becomes null.
>>>>>
>>>>> Quite strange in a single threaded application.
>>>>>
>>>>> Any idea what might be happening or should I delve into assembly?
>>>>>
>>>>> --
>>>>> Paulo
>>>>
>>>> Delve delve delve. Is this in an optimised build?
>>>
>>> I found out the cause, apparently std.container.Array destroys the  
>>> memory used by reference types as well (e.g. classes).
>>>
>>> The small example below reproduces the error.
>>>
>>> Apparently the way Array manages the memory on its own invalidates the  
>>> reference pointed by node, as I assume bad == node, but its memory is  
>>> invalid.
>>>
>>> import std.stdio;
>>> import std.container;
>>>
>>>
>>> class Node {
>>> }
>>>
>>> Node indentity (Node n)
>>> {
>>>    return n;
>>> }
>>>
>>> Node badIndentity (Node n)
>>> {
>>>    Array!Node data;
>>>    data.insert(n);
>>>    return data.front();
>>> }
>>>
>>> int  main(string[] args)
>>> {
>>>    auto node = new Node();
>>>    auto n = indentity (node);
>>>    writefln("Hello the address is %s", n);
>>>    auto bad = badIndentity (node);
>>>    writefln("Hello the address is %s", bad);
>>>
>>>    return 0;
>>> }
>>
>> This reminds me of the question I had about the use of appender.  
>> (http://forum.dlang.org/thread/xfnvtlzyolmtncsmmqqi@forum.dlang.org)
>>
>> The internal memory management of containers and appender can be the  
>> source of subtle bugs. For cases like your badIndentity function,  
>> Objective-C has autorelease, so it's only released when the program is  
>> done with the value.
>> Out of interest, why would you write a function like badIndentity this  
>> way? Or is it just a proof of concept?
>
>
> This was only to show you how to reproduce the error.
>
> On my application I use Array as a backing store for a BinaryHeap used  
> to store the nodes that are available on the A* open list.
>
> If this usage of Array is correct and the destroy method is misbehaving,  
> I can create a bug for it.
>
> I assume Array should manage its own memory but not touch the memory  
> that belongs to reference types stored on it. At least the documentation  
> doesn't say otherwise.

This is a side effect of classes being first-class reference types. Array  
needs to call destroy on structs, but not on classes. Sort of a "shallow  
destroy."

It's an interesting bug.

-Steve


More information about the Digitalmars-d-learn mailing list