destructors order not guaranteed?

Alex Martelli aleaxit at yahoo.com
Thu Nov 2 05:52:40 EST 2000


"William S. Lear" <rael at zopyra.com> wrote in message
news:87hf5rdmsa.fsf at lisa.zopyra.com...
> "Alex Martelli" <aleaxit at yahoo.com> writes:
> > ...         Thus, [Python has] no (e.g.) dangling-references problem,
> > but no elegant automatic-LIFO discipline, either ...
>
> I think the elegant automatic-LIFO discipline is very valuable.  Why

I think you've still failed to _show_ that value, beyond
proclaiming it.  If you clarify (to yourself and to us)
where that value comes from (in the context of Python,
without assuming 'stack-resident' objects &c), we'll all
be better placed to understand exactly what it IS that
you desire, and perhaps help you obtain it.


> could this not be guaranteed in Python?

As I have repeatedly (and, apparently, fruitlessly) tried
to explain, it is not even clear exactly what one should
be 'guaranteeing'.  C++, for objects whose lifetimes are
as dynamic as all of Python objects' are, guarantees zilch:
once you've made an object with, say, "new foo(1)", it's
totally up to you to "delete" that object when appropriate.

Only for stack-resident objects ('auto' storage class, a
concept that is totally alien to Python, Java, and every
other OO language I know except for C++) is there any
guarantee in C++ (and it comes with a guarantee of dangling
pointers and crashes if the address of an auto-object is
saved and used beyond its stack-frame's lifetime -- which
would be totally unacceptable for Python).


> If I remember correctly,
> Frederick Lundh says that there is not even a guarantee that
> destructors will be called.  I find this notion inelegant and
> counter-intuitive, but perhaps my intuition is pointed in the wrong
> direction.

You do understand that NO language on earth gives any
"guarantee that destructors will be called" in the GENERAL
case, right?  In C++, once you've generated an object
with "new foo(1)", there is no language guarantee that
the corresponding delete will ever be called, and thus
no guarantee whatsoever that the object's destructor
will be called, of course.  It's totally up to you, as
a programmer, to try and ensure delete is called when
it's right to call it; you also have the huge added
responsibility of ensuring that delete is *NOT* called
prematurely, i.e., when pointers/references to the
object are still extant and may be used; Python, like
Java & every other OO language I know except C++,
relieves you of this latter issue -- the object IS
guaranteed to remain alive as long as references to
it exist, no dangling-reference crashes can exist.

What C++ does in addition is define a special storage
class of objects which are not subject to the normal
rules -- stack-resident, aka 'auto', objects (it also
has another storage class yet, 'static', for which
other and different rules yet apply -- unfounded
expectations regarding construction/destruction order
of static-lifetime objects cause frequent C++ bugs,
and ensurance-of-destruction, which does apply to
static-lifetime objects, often causes extremely long
and sometimes unacceptable delays when C++ programs
terminate -- to the point that actual applications
written in C++, more often than not, bypass the rule
by terminating in system-dependent ways that save
the huge and mostly-useless overhead-on-exit...).

If Python became the only language on Earth to ensure
destruction of _every_ object (let alone, that the
destruction happens in some special order...), it
would basically lose its current outstanding ability
to "play well with others": no more could you have
Python implementations that generate code for general
existing frameworks.  Jython, for example, generates
code for the Java Virtual Machine (JVM) from Python
sources; Python.NET, similarly, generates MSIL code
(Microsoft Intermediate Language -- for the MS .NET
framework).  Both JVM and MSIL use mark-and-sweep
garbage collection: objects to which no accessible
reference remains MAY be finalized IF AND WHEN the
runtime system comes around to it.  No language with
"guaranteed-destruction" semantics can generate code
for "first-class" (fully interoperable) objects in
such frameworks; it will always remain a "second
class citizen".

Python is a highly pragmatical language, putting
eminently practical considerations far ahead of any
"theoretical purity" issue.  In this, it's very much
in line with other notoriously pragmatical languages,
such as C or C++; if it comes out more elegantly in
many cases, it's because of different objectives
[Python never places as much emphasis on runtime
performance as them, in particular...], as well of
course as Guido-and-friends' excellent taste in
matters of language [which is NOT to disparage, say,
Ritchie or Stroustrup; they _were_ operating under
different constraints and priorities!].

So, unless you can make a truly compelling case for
guaranteed-destruction (much less guaranteed-order),
subjective issues of 'elegance' are unlikely to
overwhelm the huge practical advantages of good,
first-class cooperation in such frameworks as JVM
and .NET...


Alex






More information about the Python-list mailing list