Thread overview
Noob question about structs allocation
Oct 15, 2018
IM
Oct 15, 2018
Basile B.
Oct 15, 2018
IM
Oct 15, 2018
Laurent Tréguier
Oct 15, 2018
Mike Parker
October 15, 2018
I probably used to know the answer to this question, but it's been a long time since I last used D, and I don't remember. Suppose we have:

struct S {
  int num;
}

Would allocating an instance on the heap using:

S* s = new S;

use the GC, or do we have to call destroy() or delete on s ourselves?
October 15, 2018
On Monday, 15 October 2018 at 03:19:07 UTC, IM wrote:
> I probably used to know the answer to this question, but it's been a long time since I last used D, and I don't remember. Suppose we have:
>
> struct S {
>   int num;
> }
>
> Would allocating an instance on the heap using:
>
> S* s = new S;
>
> use the GC, or do we have to call destroy() or delete on s ourselves?

new is an operator that always allocates using the GC,
calling destroy yourself won't hurt either but is not necessary.
October 15, 2018
On Monday, 15 October 2018 at 03:33:04 UTC, Basile B. wrote:
> On Monday, 15 October 2018 at 03:19:07 UTC, IM wrote:
>> I probably used to know the answer to this question, but it's been a long time since I last used D, and I don't remember. Suppose we have:
>>
>> struct S {
>>   int num;
>> }
>>
>> Would allocating an instance on the heap using:
>>
>> S* s = new S;
>>
>> use the GC, or do we have to call destroy() or delete on s ourselves?
>
> new is an operator that always allocates using the GC,
> calling destroy yourself won't hurt either but is not necessary.

What is the effect of calling destroy?
- calling the destructor?
- deallocating the memory?
- both?
October 15, 2018
On Monday, 15 October 2018 at 04:14:24 UTC, IM wrote:
> What is the effect of calling destroy?
> - calling the destructor?
> - deallocating the memory?
> - both?

IIRC, it only calls the destructor, the GC will decide when to deallocate the memory.
October 15, 2018
On Monday, 15 October 2018 at 04:14:24 UTC, IM wrote:

>
> What is the effect of calling destroy?
> - calling the destructor?
> - deallocating the memory?
> - both?

It calls the destructor. The GC will deallocate the object's memory later. However, you need to be careful about how you use GC-allocated objects that have destructors. There's currently no built-in way to know when a destructor is called as part of the normal destruction process (a stack-based instance leaving its scope or a manual call to destroy) or when it's called as part of finalization, i.e. when the GC calls it. In D, we use the same destructor for both.

I recommend you read these links:

http://p0nce.github.io/d-idioms/#The-trouble-with-class-destructors
http://p0nce.github.io/d-idioms/#GC-proof-resource-class

The focus is on classes, but I think it's more important for structs. Classes are generally going to be used with default GC allocation, meaning their destructors are always finalzers. With a struct, it's not unrealistic to anticipate instances will be allocated on the stack, the non-GC heap, or the GC heap. In that case, the conflation of finalization and destruction is something you have to pay special attention to. If you don't, you can dig yourself an architectural hole that might not even be apparent until you're well and truly into it.

Unfortunately, there's currently no direct means in the public API of distinguishing the two cases. The second link above demonstrates a workaround that makes it possible. While less than ideal, it's all we've got at the moment.

I've got an unpublished blog post, the next in the GC series at the D blog, on hold right now because of this. I'm hoping we can get something done about it:

https://issues.dlang.org/show_bug.cgi?id=17563