www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - typeid + toString = runtime error

reply "Zhenya" <zheny list.ru> writes:
Hi!
Explain me please why this code fails in runtime:

import std.stdio;

class Foo
{
	~this() {writeln(typeid(this).toString ~ "is dead");}
}

void main()
{
	new Foo;
}

Application error:
core.exception.InvalidMemoryOperationError
Dec 30 2012
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 12/30/2012 07:32 AM, Zhenya wrote:
 Hi!
 Explain me please why this code fails in runtime:

 import std.stdio;

 class Foo
 {
 ~this() {writeln(typeid(this).toString ~ "is dead");}
 }

 void main()
 {
 new Foo;
 }

 Application error:
 core.exception.InvalidMemoryOperationError
My guess is that by the time that destructor is executed, the runtime has been shut down sufficiently that the ~ operator cannot work. The following has the same error: import std.stdio; string foo() { return "abc"; } class Foo { ~this() {writeln(foo() ~ "xyz");} } void main() { new Foo; } Ali
Dec 30 2012
next sibling parent reply "Zhenya" <zheny list.ru> writes:
On Sunday, 30 December 2012 at 16:04:48 UTC, Ali Çehreli wrote:
 On 12/30/2012 07:32 AM, Zhenya wrote:
 Hi!
 Explain me please why this code fails in runtime:

 import std.stdio;

 class Foo
 {
 ~this() {writeln(typeid(this).toString ~ "is dead");}
 }

 void main()
 {
 new Foo;
 }

 Application error:
 core.exception.InvalidMemoryOperationError
My guess is that by the time that destructor is executed, the runtime has been shut down sufficiently that the ~ operator cannot work. The following has the same error: import std.stdio; string foo() { return "abc"; } class Foo { ~this() {writeln(foo() ~ "xyz");} } void main() { new Foo; } Ali
Thank you,now all is clear for me.
Dec 30 2012
parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 12/30/12, Zhenya <zheny list.ru> wrote:
 Thank you,now all is clear for me.
You can however use printf.
Dec 30 2012
prev sibling next sibling parent reply "Namespace" <rswhite4 googlemail.com> writes:
As far as I know this is because a class destructor is not a 
finalizer.
Dec 30 2012
parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 12/30/2012 08:11 AM, Namespace wrote:
 As far as I know this is because a class destructor is not a finalizer.
Thanks. It is a good way of looking at this issue. Wikipedia describes the differences as "Unlike destructors, finalizers are usually not deterministic. A destructor is run when the program explicitly frees an object. In contrast, a finalizer is executed when the internal garbage collection system frees the object. Depending on the garbage collection method used, this may happen at an arbitrary moment after the object is freed, possibly never." (I will continue with the D terminology and call it a destructor.) Since a class destructor can be executed at any random time, the operations that are valid are very limited. Could someone provide a list on what can be done and cannot be done. Andrej Mitrovic noted that printf works but is that guaranteed, or just happens to work? Here is my partial list: * Do not access members of the object that are garbage collected themselves. The reason is, those members may have already been finalized. * Similary, do not access any garbage-collected object. * (I learned this one in this thread; is this correct?) Do not rely on the runtime, as it may have been shutdown already. * What else? Ali
Dec 30 2012
prev sibling parent reply FG <home fgda.pl> writes:
On 2012-12-30 17:04, Ali Çehreli wrote:
 Application error:
 core.exception.InvalidMemoryOperationError
My guess is that by the time that destructor is executed, the runtime has been shut down sufficiently that the ~ operator cannot work.
I've encountered this error before when using ~ in a destructor even without shutting down the program. I think the garbage collector by throwing this error tries to protect itself by disallowing the creation of any new managed objects while a collection is running. Otherwise things would get too complicated. :)
Dec 30 2012
parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 2012-12-30 17:04, Ali =C7ehreli wrote:
 Application error:
 core.exception.InvalidMemoryOperationError
The basic rule is don't call or do anything which can allocate memory in a destructor. printf doesn't allocate, and if you don't do anything that allocates you should be ok. Maybe the compiler should warn or error on attempts to allocate memory (implicitly or explicitly) in a dtor. Not sure..
Dec 30 2012
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Monday, 31 December 2012 at 00:30:58 UTC, Andrej Mitrovic 
wrote:
 The basic rule is don't call or do anything which can allocate 
 memory
 in a destructor. printf doesn't allocate, and if you don't do 
 anything
 that allocates you should be ok.
Does multi arg writeln even allocate? I don't underrstand why anyone would use ~ when writeln accepts variadic args... //---- ~this() {writeln(typeid(this).toString, "is dead");} //---- Fixed! ... right? If not, multy write? //---- ~this() { write(typeid(this).toString); write("is dead"); writeln(); } //---- I'd think being forced to use the C fprint is overkill. I use writeln in my destructors all the time, and have never encountered this problem...
Dec 31 2012
parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 12/31/2012 03:30 AM, monarch_dodra wrote:

 //----
 ~this() {writeln(typeid(this).toString, "is dead");}
 //----

 Fixed! ... right?

 If not, multy write?
That still doesn't help with the case where e.g. a value has a special toString() defined and that toString() allocates memory. Such problems make it impossible to call anything in the destructor without knowing their implementations. I wonder whether the OP's problem actually is a runtime bug? Operations like ~ should still be available in the destructors. If not, what is available? Do we know the list, inclusive or exclusive? Ali
Dec 31 2012