Thread overview | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
|
April 29, 2013 clear() causes crash? | ||||
---|---|---|---|---|
| ||||
This crashes in the last line of main: class A { void foo() {} } void main() { A a = new A(); a.foo(); clear(a); assert(a !is null); a.foo(); // crashes } As far as I understand from TDPL book, this should not crash, but it does (DMD64 v2.062, OS X). Am I misunderstanding clear()? BTW, why not make clear also change 'a' to null? |
April 29, 2013 Re: clear() causes crash? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Luís Marques | On Monday, April 29, 2013 23:04:29 =?UTF-8?B?Ikx1w61z?=.Marques <luismarques@gmail.com>@puremagic.com wrote: > This crashes in the last line of main: > > class A > { > void foo() {} > } > > void main() > { > A a = new A(); > a.foo(); > clear(a); > assert(a !is null); > a.foo(); // crashes > } > > As far as I understand from TDPL book, this should not crash, but > it does (DMD64 v2.062, OS X). Am I misunderstanding clear()? > > BTW, why not make clear also change 'a' to null? I think that what TDPL says about clear may be outdated (I don't recall exactly what it said). But clear destroys the class object and zeroes out the vtbl, and it's invalid to do anything with the object after that. It's purely for cases where you want to destroy the object without waiting for the GC to do it (but it doesn't free any memory, so it's pretty much only of use for making sure that the destructor/finalizer gets run). It's very much on purpose that the app crashes when you use an object which you called clear on. Also, clear has been renamed to destroy (leaving clear as an alias to destroy), so new code should be using destroy. - Jonathan M Davis |
April 30, 2013 Re: clear() causes crash? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | On Monday, 29 April 2013 at 21:58:46 UTC, Jonathan M Davis wrote:
> zeroes out the vtbl
Hmm, I was expecting that DMD, at least in -release mode, optimize foo() to a direct call, since there's no inheritance.
|
April 30, 2013 Re: clear() causes crash? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Luís Marques | On Tuesday, 30 April 2013 at 18:54:45 UTC, Luís Marques wrote:
> On Monday, 29 April 2013 at 21:58:46 UTC, Jonathan M Davis wrote:
>> zeroes out the vtbl
>
> Hmm, I was expecting that DMD, at least in -release mode, optimize foo() to a direct call, since there's no inheritance.
It was discussed a lot of times in this newsgroup, you can google it quite easily. To sum up: it really can't, unless it is marked as final.
|
April 30, 2013 Re: clear() causes crash? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dicebot | On Tuesday, April 30, 2013 20:59:17 Dicebot wrote:
> On Tuesday, 30 April 2013 at 18:54:45 UTC, Luís Marques wrote:
> > On Monday, 29 April 2013 at 21:58:46 UTC, Jonathan M Davis
> >
> > wrote:
> >> zeroes out the vtbl
> >
> > Hmm, I was expecting that DMD, at least in -release mode, optimize foo() to a direct call, since there's no inheritance.
>
> It was discussed a lot of times in this newsgroup, you can google it quite easily. To sum up: it really can't, unless it is marked as final.
It pretty much comes down to the fact that the compiler can't possibly know that there's no inheritance, because it doesn't have the whole list of classes in the program and _can't_ have the whole list of classes (especially once shared libraries enter the mix).
- Jonathan M Davis
|
April 30, 2013 Re: clear() causes crash? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Luís Marques | On Monday, 29 April 2013 at 21:04:30 UTC, Luís Marques wrote:
> This crashes in the last line of main:
>
> class A
> {
> void foo() {}
> }
>
> void main()
> {
> A a = new A();
> a.foo();
> clear(a);
> assert(a !is null);
> a.foo(); // crashes
> }
>
> As far as I understand from TDPL book, this should not crash, but it does (DMD64 v2.062, OS X). Am I misunderstanding clear()?
>
> BTW, why not make clear also change 'a' to null?
Hasn't 'clear' been renamed to 'destroy'?
|
April 30, 2013 Re: clear() causes crash? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mafi | On Tuesday, April 30, 2013 21:47:43 Mafi wrote:
> Hasn't 'clear' been renamed to 'destroy'?
Yes, but an alias to clear still exists, and TDPL talks about clear, not destroy, so anyone reading TDPL would still expect it to be clear.
- Jonathan M Davis
|
May 11, 2013 Re: clear() causes crash? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Luís Marques | 30.04.2013 1:04, "Luís Marques" <luismarques@gmail.com>" пишет: > This crashes in the last line of main: > > class A > { > void foo() {} > } > > void main() > { > A a = new A(); > a.foo(); > clear(a); > assert(a !is null); > a.foo(); // crashes > } > > As far as I understand from TDPL book, this should not crash, but it > does (DMD64 v2.062, OS X). Am I misunderstanding clear()? > > BTW, why not make clear also change 'a' to null? Ideally is should throw with pretty message but it isn't implemented. See Issue 8139 - Make objects really disposable by addition of "Object finalized" assertion [1]. IMO, also `destroy` (renamed `clear`) looks like the worst mistake in D runtime and I'd recommend to not use it (or better recompile druntime+phobos without it for your own use). See Issue 9139 - `destroy` is dangerous and inconsistent [2]. Use `unstd.lifetime.finalizeClassInstance` [3] and friends for user-defined lifetime implementation to avoid serious problems. [1] http://d.puremagic.com/issues/show_bug.cgi?id=8139 [2] http://d.puremagic.com/issues/show_bug.cgi?id=9139 [3] http://denis-sh.github.io/phobos-additions/unstd.lifetime.html#finalizeClassInstance -- Денис В. Шеломовский Denis V. Shelomovskij |
May 13, 2013 Re: clear() causes crash? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Denis Shelomovskij | On Fri, 10 May 2013 22:37:43 -0400, Denis Shelomovskij <verylonglogin.reg@gmail.com> wrote: > 30.04.2013 1:04, "Luís Marques" <luismarques@gmail.com>" пишет: >> This crashes in the last line of main: >> >> class A >> { >> void foo() {} >> } >> >> void main() >> { >> A a = new A(); >> a.foo(); >> clear(a); >> assert(a !is null); >> a.foo(); // crashes >> } >> >> As far as I understand from TDPL book, this should not crash, but it >> does (DMD64 v2.062, OS X). Am I misunderstanding clear()? TDPL states that the object is required to be in a valid state. This necessarily requires calling a constructor on an object, as an object has no valid initial state. There are major issues with that requirement, though: 1. How to call a ctor for an object that does not have a default ctor? In other words, it requires valid ctor parameters, which the runtime cannot possibly know. 2. What if the ctor adds the class instance to a global or some other rooted memory item? That is, what if the entire point of clearing it is so it was not pointed to as being allocated, so the GC would remove it. So the decision was made (correctly) to simply make any object that was destroyed be an invalid object. structs will return to their .init value (which may also be invalid depending on the struct). >> BTW, why not make clear also change 'a' to null? That could also be done, but it is superficial: auto b = a; destroy(a); b.foo(); The only valid thing to do with a after destroying it is to stop using it, and all other references to that instance. > > Ideally is should throw with pretty message but it isn't implemented. See Issue 8139 - Make objects really disposable by addition of "Object finalized" assertion [1]. > > IMO, also `destroy` (renamed `clear`) looks like the worst mistake in D runtime and I'd recommend to not use it (or better recompile druntime+phobos without it for your own use). See Issue 9139 - `destroy` is dangerous and inconsistent [2]. Use `unstd.lifetime.finalizeClassInstance` [3] and friends for user-defined lifetime implementation to avoid serious problems. > > [1] http://d.puremagic.com/issues/show_bug.cgi?id=8139 > [2] http://d.puremagic.com/issues/show_bug.cgi?id=9139 > [3] http://denis-sh.github.io/phobos-additions/unstd.lifetime.html#finalizeClassInstance > I'm curious why you think it is bad. All you have said here is that it is bad, not why. Even bug 9139 says "look at how horrible this is" but doesn't explain why. The point of destroy is to call destructors without deallocation. The original charter said to leave the object in a default state, but that requires re-calling the constructor. In the latest iteration, it simply calls the finalize function in the runtime. you are not supposed to use it after calling destroy. Not being defensive, I simply don't understand the objection. -Steve |
Copyright © 1999-2021 by the D Language Foundation