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.