May 26, 2012
On 05/26/12 13:35, Jacob Carlborg wrote:
> On 2012-05-25 14:05, foobar wrote:
> 
>>> If you have a pointer to a struct you don't know how it was created. It's possible it's been created with "new", which means the garbage collector needs to delete it.
>>
>> let's say we add two classes:
>> class FooA {
>> A a;
>> }
>> class FooPA {
>> A* pa;
>> }
>>
>> For the first case, both the class and the struct share the same lifetime thus when an instance of FooA is GC-ed, the GC would call A's d-tor and allow it to do what-ever (self) cleaning it requires. This means the d-tor will always be called.
> 
> Is that the cases even if the destructor of FooA isn't called?
> 
>> For the second case, The GC will only scan "pa" to find inner class
>> instances but will *not* handle the struct value itself.
>> In order to clean what "pa" points to, you need to explicitly call the
>> destructor yourself.
> 
> Are you saying that the GC won't collect a struct allocated with "new"?
> 
> http://dlang.org/expression.html#NewExpression
> 
> "NewExpressions are used to allocate memory on the garbage collected heap...". I though that everything allocated via the GC was also collected by the GC.

Everything allocated is collected, though not necessarily destructed. In case of structs, the GC currently doesn't know about the dtors, so those are never called.

   import std.stdio;
   struct S { ~this() { writeln("never called"); } }
   void main() { S* sp; while (1) sp = new S(); }

Right now you have to use a class if you need dtors for heap allocated objects.

artur
May 26, 2012
On 2012-05-26 14:28, foobar wrote:

> Huh? In my model FooA has no destructor.

Hm, right. But if a destructor of a class isn't guaranteed to be called, how can it guarantee that the struct's destructor will be called?

> I indeed propose that structs allocated with "new" will be put in region
> of the heap *not* managed by the GC. It's a tiny price to pay to get
> more orthogonal semantics which are easier to reason about.
> Please note that this only affects code that directly uses pointers
> which is not common in D and is geared towards more advanced use cases
> where the programmer will likely want to manage the memory explicitly
> anyway.

I see.

-- 
/Jacob Carlborg
May 26, 2012
Le 25/05/2012 16:35, Andrei Alexandrescu a écrit :
> On 5/25/12 12:07 AM, Mehrdad wrote:
>> Now, there are two ways a FileStream can get destroyed:
>>
>> 1. Through a manual call to FileStream.Dispose(). In this case, all
>> embedded objects (e.g. SafeFileHandle) are *guaranteed* to be valid, so
>> we simply flush the file and call SafeFileHandle.Dispose() to dispose of
>> the managed resources, and then dispose of all the unmanaged resources
>> (which are primitive fields, guaranteed to be accessible). Furthermore,
>> the object suppresses its own finalizer.
>>
>> 2. Through a garbage-collected call to ~FileStream(). In this case, the
>> managed resources such as SafeFileHandle will be (or is already)
>> destroyed SEPARATELY, and so we do _NOT_ access them. We ONLY dispose of
>> the unmanaged resources, if any, and let the managed resources take care
>> of themselves.
>
> What happens in C# if an object A that has a field referring to object
> B, and the object B has in turn a field referring to object A? That is:
>
> class C { C another; ~this() { writeln(another.another); } }
>
> void main() {
> auto a = new C;
> auto b = new C;
> a.another = b;
> b.another = a;
> }
>
> What happens then? Will the GC nullify references to destroyed objects,
> or will it put them in a zombie state?
>
>
> Thanks,
>
> Andrei

Here is what I suggest :
1/ what is in ~this stay in ~this. You cannot escape a reference to this or anything reached throw this of ~this. In other terms, the hidden this parameter get scope storage class. This avoid resurrection (something we really want, it have caused much trouble in java).
2/ The GC will call all finalizers on objects (here a and b) when they are garbage. Finalizers are called in undefined order.
3/ The GC will recycle the memory after all finalizers ran.

In the example above, both writeln will executed and then, both object's memory will be recycled.
November 12, 2013
On Friday, 25 May 2012 at 14:35:58 UTC, Andrei Alexandrescu wrote:
>
> What happens in C# if an object A that has a field referring to object B, and the object B has in turn a field referring to object A? That is:
>
> class C { C another; ~this() { writeln(another.another); } }
>
> void main() {
>     auto a = new C;
>     auto b = new C;
>     a.another = b;
>     b.another = a;
> }
>
> What happens then? Will the GC nullify references to destroyed objects, or will it put them in a zombie state?
>
>
> Thanks,
>
> Andrei

In this case the a and b objects will be collected by GC and memory freed.
It's a one of most popular questions about .NET GC. Maybe something was changed in .NET >= 4.5.

I have another question: there available a good example of idiomatic destructor usage in the D?
Something without calling a rt_ hooks on destroy?
1 2 3 4 5 6 7
Next ›   Last »