www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Is array concatenation allowed in the class destructor?

reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
This issue has come up on the D.learn forum recently. The following 
program terminates with core.exception.InvalidMemoryOperationError. 
(Tested with dmd 2.061 and 2.060)

string foo()
{
     return "a";
}

class Foo
{
     ~this()
     {
         auto s = foo() ~ "b";
     }
}

void main()
{
     new Foo;
}

My guess is that the destructor is being executed at a point where the 
runtime is not in a state where allocating memory is allowed.

Has the programmer made a mistake? What operations are safe in a class 
destructor? (I think the question is valid for the destructors of 
GC-owned struct objects as well.)

Since the programmer should not be expected to know the implementations 
of every function, the only safe action is to not call any function in a 
destructor at all, as that function may be allocating dynamic memory 
under certain conditions. I hope I am wrong. :) Can we expect the 
runtime be cooperative until all finalizers are executed?

Ali
Jan 02 2013
parent "Maxim Fomin" <maxim maxim-fomin.ru> writes:
On Wednesday, 2 January 2013 at 18:09:34 UTC, Ali Çehreli wrote:
 This issue has come up on the D.learn forum recently. The 
 following program terminates with 
 core.exception.InvalidMemoryOperationError. (Tested with dmd 
 2.061 and 2.060)

 string foo()
 {
     return "a";
 }

 class Foo
 {
     ~this()
     {
         auto s = foo() ~ "b";
     }
 }

 void main()
 {
     new Foo;
 }

It is obvious that dtor causes GC activity and current GC is not reentrant. If you change dtor to for e.x. ~this() { doSomething(); }, so now it is impossible to make conclusion without doSomething() source.
 My guess is that the destructor is being executed at a point 
 where the runtime is not in a state where allocating memory is 
 allowed.

Yes.
 Has the programmer made a mistake? What operations are safe in 
 a class destructor? (I think the question is valid for the 
 destructors of GC-owned struct objects as well.)

In general, operations that involve GC inside class dtors that are run after garbage process have been started, lead to InvalidMemoryOperationError exceptions. This means that if you cannot guarantee that class destructors are called before garbage collection, you will have problems.
 Since the programmer should not be expected to know the 
 implementations of every function, the only safe action is to 
 not call any function in a destructor at all, as that function 
 may be allocating dynamic memory under certain conditions. I 
 hope I am wrong. :) Can we expect the runtime be cooperative 
 until all finalizers are executed?

 Ali

Yes, necessity to restrict operations in class dtors are inconvenient. The solution is to fix the GC.
Jan 02 2013