Thread overview | |||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
March 04, 2015 What is going on here? | ||||
---|---|---|---|---|
| ||||
import std.stdio; struct A { int a = 3; this( int var ) { a += var; } ~this() { writeln("A down ", a); } } struct B { A a; this( int var ) { a = A(var+1); throw new Exception("An exception"); } } void main() { try { auto b = B(2); } catch( Exception ex ) { } } I'd expect A's destructor to run, which does not seem to be the case. Compiled with dmd 2.066.1 Shachar |
March 04, 2015 Re: What is going on here? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Shachar Shemesh | On 3/4/15 8:43 AM, Shachar Shemesh wrote:
> I'd expect A's destructor to run, which does not seem to be the case.
I believe destructors are not run when you throw inside a constructor. So plan to deallocate if the ctor throws:
a = A(var + 1);
scope(failure) destroy(a);
-Steve
|
March 04, 2015 Re: What is going on here? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Wednesday, 4 March 2015 at 15:43:15 UTC, Steven Schveighoffer wrote: > On 3/4/15 8:43 AM, Shachar Shemesh wrote: > >> I'd expect A's destructor to run, which does not seem to be the case. > > > I believe destructors are not run when you throw inside a constructor. So plan to deallocate if the ctor throws: > > a = A(var + 1); > scope(failure) destroy(a); The spec says [1], that the first write to a field in a class's constructor is a construction, not an assignment. I assume this applies to structs as well. If so, this implies that the compiler already knows at each point which fields are already constructed. Why doesn't it automatically insert appropriate destructor calls then? [1] http://dlang.org/class.html#field-init |
March 04, 2015 Re: What is going on here? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Marc Schütz | On 3/4/15 11:32 AM, "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm@gmx.net>" wrote:
> On Wednesday, 4 March 2015 at 15:43:15 UTC, Steven Schveighoffer wrote:
>> On 3/4/15 8:43 AM, Shachar Shemesh wrote:
>>
>>> I'd expect A's destructor to run, which does not seem to be the case.
>>
>>
>> I believe destructors are not run when you throw inside a constructor.
>> So plan to deallocate if the ctor throws:
>>
>> a = A(var + 1);
>> scope(failure) destroy(a);
>
> The spec says [1], that the first write to a field in a class's
> constructor is a construction, not an assignment. I assume this applies
> to structs as well. If so, this implies that the compiler already knows
> at each point which fields are already constructed. Why doesn't it
> automatically insert appropriate destructor calls then?
>
> [1] http://dlang.org/class.html#field-init
That is talking about initializing immutable fields. The dtor is not called when the exception is thrown, but this doesn't seem to be in the spec (I don't remember where I read it, but I'm sure it's an intentional decision). D provides a mechanism to destroy partially constructed objects, use scope(failure).
-Steve
|
March 04, 2015 Re: What is going on here? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Wednesday, 4 March 2015 at 17:19:31 UTC, Steven Schveighoffer wrote: > On 3/4/15 11:32 AM, "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm@gmx.net>" wrote: >> On Wednesday, 4 March 2015 at 15:43:15 UTC, Steven Schveighoffer wrote: >>> On 3/4/15 8:43 AM, Shachar Shemesh wrote: >>> >>>> I'd expect A's destructor to run, which does not seem to be the case. >>> >>> >>> I believe destructors are not run when you throw inside a constructor. >>> So plan to deallocate if the ctor throws: >>> >>> a = A(var + 1); >>> scope(failure) destroy(a); >> >> The spec says [1], that the first write to a field in a class's >> constructor is a construction, not an assignment. I assume this applies >> to structs as well. If so, this implies that the compiler already knows >> at each point which fields are already constructed. Why doesn't it >> automatically insert appropriate destructor calls then? >> >> [1] http://dlang.org/class.html#field-init > > That is talking about initializing immutable fields. That's true, but I was going to argue that if the compiler is able to check this for immutable fields, there is no reason why it couldn't also do it for mutable ones. But now I see that it only uses an imprecise heuristic that is probably too coarse to extend it to mutable fields. In fact, I even found a loop-hole, which I've filed here: https://issues.dlang.org/show_bug.cgi?id=14245 > The dtor is not called when the exception is thrown, but this doesn't seem to be in the spec (I don't remember where I read it, but I'm sure it's an intentional decision). D provides a mechanism to destroy partially constructed objects, use scope(failure). Oh no, another hidden trap :-( `scope(failure)` is only a workaround if you're aware of it. I think the heuristic for immutable fields could be adapted to be applicable to mutable fields: the first assignment to a field must not be inside a loop or behind a label. |
March 04, 2015 Re: What is going on here? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On 04/03/15 17:43, Steven Schveighoffer wrote:
> On 3/4/15 8:43 AM, Shachar Shemesh wrote:
>
>> I'd expect A's destructor to run, which does not seem to be the case.
>
>
> I believe destructors are not run when you throw inside a constructor.
> So plan to deallocate if the ctor throws:
>
> a = A(var + 1);
> scope(failure) destroy(a);
>
> -Steve
That's pretty horrible. So now I need to keep track of the implementation of my members to figure out whether it is okay to skip the destructor or not.
All of this from a language that claims to support RAII, which was invented precisely so the programmer does not have to keep track of those things.
I think this is precisely the sort of corner cases that drive people away from C++.
Shachar
|
March 04, 2015 Re: What is going on here? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On 03/04/2015 07:43 AM, Steven Schveighoffer wrote:
> On 3/4/15 8:43 AM, Shachar Shemesh wrote:
>
>> I'd expect A's destructor to run, which does not seem to be the case.
>
>
> I believe destructors are not run when you throw inside a constructor.
> So plan to deallocate if the ctor throws:
>
> a = A(var + 1);
> scope(failure) destroy(a);
>
> -Steve
I don't want that. :)
Even C++ gets this right.
Ali
|
March 04, 2015 Re: What is going on here? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Wednesday, 4 March 2015 at 19:36:20 UTC, Ali Çehreli wrote: > On 03/04/2015 07:43 AM, Steven Schveighoffer wrote: >> On 3/4/15 8:43 AM, Shachar Shemesh wrote: >> >>> I'd expect A's destructor to run, which does not seem to be the case. >> >> >> I believe destructors are not run when you throw inside a constructor. >> So plan to deallocate if the ctor throws: >> >> a = A(var + 1); >> scope(failure) destroy(a); >> >> -Steve > > I don't want that. :) > Then vote here :-P https://issues.dlang.org/show_bug.cgi?id=14246 |
March 05, 2015 Re: What is going on here? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Marc Schütz | On Wednesday, 4 March 2015 at 20:37:20 UTC, Marc Schütz wrote:
> On Wednesday, 4 March 2015 at 19:36:20 UTC, Ali Çehreli wrote:
>> On 03/04/2015 07:43 AM, Steven Schveighoffer wrote:
>>> I believe destructors are not run when you throw inside a constructor.
>>> So plan to deallocate if the ctor throws:
>>>
>>> a = A(var + 1);
>>> scope(failure) destroy(a);
>>>
>>> -Steve
>>
>> I don't want that. :)
>>
>
> Then vote here :-P
> https://issues.dlang.org/show_bug.cgi?id=14246
Added my vote. The construction heuristic needs to become more sophisticated and well-defined anyway.
|
March 05, 2015 Re: What is going on here? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jakob Ovrum | On Thursday, 5 March 2015 at 00:03:37 UTC, Jakob Ovrum wrote:
> On Wednesday, 4 March 2015 at 20:37:20 UTC, Marc Schütz wrote:
>> On Wednesday, 4 March 2015 at 19:36:20 UTC, Ali Çehreli wrote:
>>> On 03/04/2015 07:43 AM, Steven Schveighoffer wrote:
>>>> I believe destructors are not run when you throw inside a constructor.
>>>> So plan to deallocate if the ctor throws:
>>>>
>>>> a = A(var + 1);
>>>> scope(failure) destroy(a);
>>>>
>>>> -Steve
>>>
>>> I don't want that. :)
>>>
>>
>> Then vote here :-P
>> https://issues.dlang.org/show_bug.cgi?id=14246
>
> Added my vote. The construction heuristic needs to become more sophisticated and well-defined anyway.
Would be nice if votes on bugzilla mattered, like putting highly voted opened bugs on the front page of dlang.org.
|
Copyright © 1999-2021 by the D Language Foundation