Ownership semantics

maik klein via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sun Jan 31 12:31:24 PST 2016


On Sunday, 31 January 2016 at 20:20:52 UTC, Steven Schveighoffer 
wrote:
> On 1/31/16 3:15 PM, Matt Elkins wrote:
>> On Sunday, 31 January 2016 at 20:11:07 UTC, Matt Elkins wrote:
>>> On Sunday, 31 January 2016 at 20:10:03 UTC, Matt Elkins wrote:
>>>> On Sunday, 31 January 2016 at 20:07:26 UTC, Steven 
>>>> Schveighoffer wrote:
>>>>> What is likely happening is that ptr is already collected, 
>>>>> and you
>>>>> are invalidly attempting to re-free it.
>>>>
>>>> The GC can collect this memory even though there is still an
>>>> outstanding root-reachable pointer to it?
>>>
>>> Or maybe it isn't root-reachable?
>>
>> No, it is still present even if root-reachable:
>>
>> [code]
>> unittest
>> {
>>      import std.algorithm;
>>
>>      int* x;
>>      {
>>          auto map = new UniquePtr!int[1];
>>          auto uniqueX = UniquePtr!int(5);
>>          x = uniqueX.get();
>>          map[0] = move(uniqueX);
>>      }
>> }
>> [/code]
>>
>> [output]
>> core.exception.InvalidMemoryOperationError at src\core\exception.d(679):
>> Invalid memory operation
>> ----------------
>> Program exited with code 1
>> Made 632560 for this 18FD90
>> Disposing null for this 18FD70
>> Disposed null for this 18FD70
>> Disposing null for this 18FD90
>> Disposed null for this 18FD90
>> All unit tests have been run successfully.
>> Disposing 632560 for this 632550
>> [/output]
>
> Oh, nevermind. This is actually simpler.
>
> You can't do memory operations inside a destructor during 
> collection. I forgot about that.
>
> But the rule I stated is still in force.
>
> -Steve
Honestly I don't quite understand why it would refree the ptr, 
but switching to malloc does seem to solve the problem.

struct UniquePtr(T) {
     import std.experimental.allocator;
     private T* ptr = null;
     IAllocator alloc;
     @disable this(this); // This disables both copy construction 
and opAssign

     this(Args...)(auto ref Args args){
         import std.experimental.allocator.mallocator;
         alloc = allocatorObject(Mallocator.instance);
         ptr = alloc.make!T(args);
     }

     ~this() {
         alloc.dispose(ptr);
     }

     inout(T)* get() inout {
         return ptr;
     }

     // Move operations
     this(UniquePtr!T that) {
         this.ptr = that.ptr;
         that.ptr = null;
     }

     ref UniquePtr!T opAssign(UniquePtr!T that) { // Notice no 
"ref" on "that"
         import std.algorithm.mutation;
         swap(this.ptr, that.ptr); // We change it anyways, 
because it's a temporary
         return this;
     }
}



More information about the Digitalmars-d-learn mailing list