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