Topic: Object code assumptions


Author: skaller@nospam.com.au ("John Max Skaller")
Date: Thu, 28 Oct 2004 16:31:40 GMT
Raw View
On Thu, 28 Oct 2004 01:07:20 +0000, johnchx wrote:

> skaller@nospam.com.au ("John Max Skaller") wrote
>> johnchx wrote:
>> > nagle@animats.com (John Nagle) wrote
>> > >     Suppose you have an C++ implementation that manages
>> > > DLLs (or some other platform-dependent form of "big
>> > > objects) by keeping a count of the number of instances
>> > > of the classes implemented in the DLL.  The count goes
>> > > up for "new", and down for "delete".  When the instance
>> > > count goes to 0, the DLL is released.
>> >
>> > How can I suppose that?
>> >
>> > If by "a C++ implementation" you mean "a standard-conforming C++
>> > implementation," then it cannot have the semantics you describe.
>> >
>> > Perhaps what you mean is that the C++ standard ought to be amended to
>> > permit this.
>>
>> It seems useful to consider what could be done in the Standard
>> to provide better support for dynamic loading.
>>
>
> Agreed.
>
>> It isn't clear you're entirely right about what's conforming.
>> I don't see that a compiler fails to conform just because
>> it supports dynamic loading.
>
> That's not what I meant. I meant that the specific *unloading*
> semantics that were described (unloading the DLL at the end of the
> lifetime of the last class instance) would not be conforming.

OK, accepted, but provided you first accept that linking
is vendor specified -- so the code is only conforming
provided the vendor says dynamic loading is part of the linking
process.

If the vendor doesn't support it, the code isn't well defined,
because it isn't actually 'part of the program'.

So the real question seems to be whether it is possible
for the vendor to say it's ok to load and unload code,
but *with some additional caveats*, in such as way that
you can write useful code that could be portable.

In one sense, the purpose of a Standard is nothing more
than to abbreviate the vendor's specifications eg they
can say "conforms to XXX with these parameters .."
instead of providing a 500 page document as a spec.

So .. if I unload a DLL after the last object is dead,
I may STILL get into problems. What *other* constraints
must be satisfied for the unload to work at this time?
Is there better time, meaning, one with less constraints
on the programmer, but which allows automatic calculation
of when it's safe to unload? Are there any extensions
to the Standard which would help implement safe automatic
unloading?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Thu, 28 Oct 2004 18:07:41 GMT
Raw View
John Max Skaller wrote:
> That clearly isn't. What if there is a pointer to some
> static data, for example a null terminated string?

I was talking about removing the code. If code and data
must be removed as a whole, then you garbage collect on
the data as well, and only remove the DLL when there are
no data or function pointers remaining.

> What about if you copied a polymorphic object created
> by DLL code .. that would contain a vtable pointer
> into the DLL.

And the vtable would be reachable, and thus so would its
contained function pointers, and the DLL would not yet be
garbage.

> I guess you could extend the garbage collection idea
> to cover *all* pointers -- provided RTTI and vtables,
> EH tables, etc, didn't contain any encoded adresses
> that would fool the collector.

Garbage collection must be an integrated part of the
entire implementation, not an add-on. Hence C++/CLI.
Then there is no "fooling" the collector.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: skaller@nospam.com.au ("John Max Skaller")
Date: Sun, 31 Oct 2004 05:23:12 GMT
Raw View
On Thu, 28 Oct 2004 18:07:41 +0000, Hyman Rosen wrote:

> Garbage collection must be an integrated part of the
> entire implementation, not an add-on.

That would be nice but isn't always entirely
practical. In my case I have to deal with existing
C++ compilers.

> Hence C++/CLI.
> Then there is no "fooling" the collector.

In C/C++ you can always fool the collector,
and there is no way to fix the problem other than
change to a language designed for collection.

Perhaps that language is a subset of C++, and
perhaps some other language, but there's no way
to make C++ work properly with a collector even
if the compiler and collector cooperate: you have
to ban certain naughty practices which are perfectly
legal C++ and can't be detected by compilers.

Any encoding of an address as something else has
this property, for example, bit fiddling.

C99 actually makes this problem significantly worse
by allowing conforming code to fiddle with integer
representations :(

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: nagle@animats.com (John Nagle)
Date: Mon, 1 Nov 2004 20:51:26 GMT
Raw View
Hyman Rosen wrote:

> John Nagle wrote:
>
>>    Suppose you have an C++ implementation that manages
>> DLLs (or some other platform-dependent form of "big
>> objects) by keeping a count of the number of instances
>> of the classes implemented in the DLL.  The count goes
>> up for "new", and down for "delete".  When the instance
>> count goes to 0, the DLL is released.
>
>
> This cannot work well in general. First of all, this does
> not allow for DLLs whose objects can be created on the
> stack, or statically, since delete is never called on them.

     I should have said "up for the constructor, down for
the destructor".  Even for static objects, destructors
are called eventually.

> Second, C++ programs may create new objects over old ones
> without ever calling delete or their destructors.

     Is that a bug, or a feature?

     Admittedly we're going to have to have some restrictions.
Obvously, using casts or unions to force objects onto memory
can cause trouble with storage allocation.

    John Nagle

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: skaller@nospam.com.au ("John Max Skaller")
Date: Thu, 21 Oct 2004 07:08:21 GMT
Raw View
On Wed, 20 Oct 2004 12:29:46 +0000, johnchx wrote:

> The example you give, a non-static member function being unable to
> continue after "delete this;", would be non-conforming.

Yes, but Max Polk originally wrote this:

"A creative new computer architecture which allows migration of executable code
in and out of existence, such as across machine boundaries or for
limited-resource mobile devices, could be invented to delete the object code
itself when the object is deleted."

Actually I just implemented this in Felix. More precisely,
you can now dynamically load  'plugins' represented
by shared libraries, invoke some functions, and when
the last function dies, the library is unloaded automatically.

To make this work for arbitrary C++ seems hard .. you'd
need to account for vtables, etc.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: ron@sensor.com (Ron Natalie)
Date: Fri, 22 Oct 2004 17:37:08 GMT
Raw View
Hyman Rosen wrote:
> Ron Natalie wrote:
>
>> This is a gray area.   Actually, the standard doesn't describe the
>> behavior
>> of an object's lifetime ending during the execution of a non-static
>> member.
>> Hence it is UNDEFINED BEHAVIOR.
>
>
> I emphatically disagree. Member functions are not part of an object.
> As described in 9.3.2/1, a member function has access to the object
> for which it was called through the 'this' pointer. As described in
> 9.3.1/2, access to unadorned members of the object are transformed
> into expressions using 'this'. Since member functions ar in no way
> associated with a specific object, there is no reason to say that
> ending the lifetime of a particular object causes undefined behavior
> during the execution of a member function. It is simply the case that
> if the lifetime of the object referred to by 'this' has ended, then
> the same rules apply as for any other pointer.

I emphaticalloy disagree with your emphatic disagreement.   :-)
Your argument reinforces my point.   A (non-static) member function
call inherently uses the this pointer.  They are VERY much associated
with the object on which they are called.   Calling a non-static
member function is as improprer after the lifetime ended as accessing
a non-static data member.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Sat, 23 Oct 2004 02:56:24 GMT
Raw View
Ron Natalie wrote:
> A (non-static) member function call inherently uses the this pointer.
 > Calling a non-static member function is as improprer after the lifetime
 > ended as accessing a non-static data member.

But that's not what we were talking about. You said that ending an
object's lifetime during execution of a non-static member function
is undefined behavior, and that's with what I am disagreeing.

Now you are talking about *calling* a member function on an object
whose lifetime has ended, and I would agree that this is undefined
behavior, because 'this' needs to be set up for the new call.

By the way, we are being imprecise in language. The lifetime of a
non-POD object ends when its destructor begins executing, and dtors
are certainly permitted to call member functions.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: skaller@nospam.com.au ("John Max Skaller")
Date: Mon, 25 Oct 2004 03:34:00 GMT
Raw View
On Thu, 21 Oct 2004 01:56:09 +0000, Hyman Rosen wrote:

> Ron Natalie wrote:
>> This is a gray area.   Actually, the standard doesn't describe the behavior
>> of an object's lifetime ending during the execution of a non-static member.
>> Hence it is UNDEFINED BEHAVIOR.
>
> I emphatically disagree. Member functions are not part of an object.
> As described in 9.3.2/1, a member function has access to the object
> for which it was called through the 'this' pointer. As described in
> 9.3.1/2, access to unadorned members of the object are transformed
> into expressions using 'this'. Since member functions ar in no way
> associated with a specific object, there is no reason to say that
> ending the lifetime of a particular object causes undefined behavior
> during the execution of a member function. It is simply the case that
> if the lifetime of the object referred to by 'this' has ended, then
> the same rules apply as for any other pointer.

You may be correct in respect of what the Standard says,
but your reasoning is suspect :)

In fact this issue was heavily debated by the committee,
meaning, it really is an issue for which the undefined
behaviour was an option.

In particular, it makes sense to use a machine register
for the 'this' pointer on some machines. And it may
be the register needs to be saved and restored.

AND it may also be doing that requires the register to
contain a valid address. In particular loading a full
segemented addres on a 386 machine *does* in fact
require that the segment register refer to a valid
descriptor, otherwise a trap is generated.

So it is, in fact, quite reasonable to mandate that the
object of a non-staic member function remain alive whilst
ANY code of a member function is executing .. and in fact
I argued that case myself. There may be other related
arguments, most of which are concerned with implementor
optimisation opportunities and portability to a wide
class of platforms.


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Mon, 25 Oct 2004 16:11:53 GMT
Raw View
John Max Skaller wrote:
> In particular, it makes sense to use a machine register
> for the 'this' pointer on some machines. And it may
> be the register needs to be saved and restored.
>
> AND it may also be doing that requires the register to
> contain a valid address.

The problem with this argument is that it applies equally
to any other pointer. Suppose I have the following code:

     struct a {
         char *p;
         a() { p = new char; b(); }
         b() { delete p; }
     };

It's perfectly plausible that a() would have p in a register,
that b() would as well, and that a() might try to reload that
register once b() returned. So there's no difference whether
b() does 'delete p;' or 'delete this;'; if registers are a
problem, it's up to the implementation to make things work
properly.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: johnchx2@yahoo.com (johnchx)
Date: Mon, 25 Oct 2004 16:11:59 GMT
Raw View
skaller@nospam.com.au ("John Max Skaller") wrote

> So it is, in fact, quite reasonable to mandate that the
> object of a non-staic member function remain alive whilst
> ANY code of a member function is executing .. and in fact
> I argued that case myself. There may be other related
> arguments, most of which are concerned with implementor
> optimisation opportunities and portability to a wide
> class of platforms.

And would this rule apply to all functions which receive pointers to
dynamically allocated objects?  I.e. are you saying that the following
should be undefined?

struct foo {
  int do_something () {return 5;}
};

int f (foo* pf, int i)
{
  int j = pf->do_something();
  delete pf;
  return i + j;
}

int main ()
{
  foo* pf = new foo;
  int k = f(pf, 20);
}

Or would it be well-defined as is, but become undefined if we made f()
a member of foo, replacing pf with the implicit this pointer
parameter?  Do we really want to create a rule that says that a member
function can't accomplish what a non-member function could?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: nagle@animats.com (John Nagle)
Date: Mon, 25 Oct 2004 18:21:59 GMT
Raw View
Ron Natalie wrote:
> Hyman Rosen wrote:
>
>> Ron Natalie wrote:

    [Regarding what seems to be a "delete(this)" argument.]

    Even Strostrup says that "this" should have been a reference.
"delete(this)" is a bad legacy concept from early versions of
C++.

    Don't try to add functionality in that area.  Deprecate it.

    John Nagle
    Animats


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: nagle@animats.com (John Nagle)
Date: Mon, 25 Oct 2004 18:52:01 GMT
Raw View
Hyman Rosen wrote:
> John Max Skaller wrote:
>
>> In particular, it makes sense to use a machine register
>> for the 'this' pointer on some machines. And it may
>> be the register needs to be saved and restored.
>>
>> AND it may also be doing that requires the register to
>> contain a valid address.
>
>
> The problem with this argument is that it applies equally
> to any other pointer.

    No, the problem is "delete this" because of when the
deletion takes place.

    Suppose you have an C++ implementation that manages
DLLs (or some other platform-dependent form of "big
objects) by keeping a count of the number of instances
of the classes implemented in the DLL.  The count goes
up for "new", and down for "delete".  When the instance
count goes to 0, the DLL is released.

    For that case, "delete p" is fine, because control is
outside the class, but "delete this" is not, because
control is inside the class.  The code will be deleted
while still being executed, and the program will fault.

    Synchronizing object loading is hard unless the rules
are clear and enforced.  Microsoft had some problems in
this area with  "Managed C++", resulting in the mess described here.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_vstechart/html/vcconMixedDLLLoadingProblem..asp

   John Nagle
   Animats

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: skaller@nospam.com.au ("John Max Skaller")
Date: Mon, 25 Oct 2004 18:51:41 GMT
Raw View
On Mon, 25 Oct 2004 16:11:53 +0000, Hyman Rosen wrote:

> John Max Skaller wrote:
>> In particular, it makes sense to use a machine register
>> for the 'this' pointer on some machines. And it may
>> be the register needs to be saved and restored.
>>
>> AND it may also be doing that requires the register to
>> contain a valid address.
>
> The problem with this argument is that it applies equally
> to any other pointer.

there's no problem with the argument. It could apply
to any pointer. But 'this' is a keyword, not just a pointer,
and it could be implemented specially, particularly since
it is likely to be heavily used. So it could have different
rules to other pointers.

In other words the tradeoff for 'this' might sensibly
be different. I'm not saying it is, just that it could be.
Two other pointers -- SP and PC -- do get special treatment,
why not 'this'?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Mon, 25 Oct 2004 19:59:07 GMT
Raw View
John Nagle wrote:
>    Suppose you have an C++ implementation that manages
> DLLs (or some other platform-dependent form of "big
> objects) by keeping a count of the number of instances
> of the classes implemented in the DLL.  The count goes
> up for "new", and down for "delete".  When the instance
> count goes to 0, the DLL is released.

This cannot work well in general. First of all, this does
not allow for DLLs whose objects can be created on the
stack, or statically, since delete is never called on them.
Second, C++ programs may create new objects over old ones
without ever calling delete or their destructors.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: brangdon@cix.co.uk (Dave Harris)
Date: Mon, 25 Oct 2004 22:26:57 GMT
Raw View
nagle@animats.com (John Nagle) wrote (abridged):
>     Suppose you have an C++ implementation that manages
> DLLs (or some other platform-dependent form of "big
> objects) by keeping a count of the number of instances
> of the classes implemented in the DLL.  The count goes
> up for "new", and down for "delete".  When the instance
> count goes to 0, the DLL is released.

That fails if a class has static methods. You need to decrement a count
when control leaves such a method. Basically, after "delete this" a
non-static member function becomes similar to a static one.

struct S {
    static void proc1( S *s ) {
        delete s;
        // More code not using s.
    }

    void proc2() {
        delete this;
        // More code not using this.
    }
};

It sounds like your implementation would unload the DLL halfway through
proc1(), which is surely wrong. If it gets proc1() right, then it can get
proc2() right the same way.

-- Dave Harris, Nottingham, UK

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: johnchx2@yahoo.com (johnchx)
Date: Mon, 25 Oct 2004 23:56:16 GMT
Raw View
nagle@animats.com (John Nagle) wrote
> Hyman Rosen wrote:

> > The problem with this argument is that it applies equally
> > to any other pointer.
>
>     No, the problem is "delete this" because of when the
> deletion takes place.
>
>     Suppose you have an C++ implementation that manages
> DLLs (or some other platform-dependent form of "big
> objects) by keeping a count of the number of instances
> of the classes implemented in the DLL.  The count goes
> up for "new", and down for "delete".  When the instance
> count goes to 0, the DLL is released.

How can I suppose that?

If by "a C++ implementation" you mean "a standard-conforming C++
implementation," then it cannot have the semantics you describe.  If
it has the semantics you describe, then it's not a C++ implementation
(or, at least, it's a non-conforming one).

Perhaps what you mean is that the C++ standard ought to be amended to
permit this.  To make that fly, however, I think you'd need to deal
with at least two issues:

(1) How to handle static members (both data members and functions)

(2) How to specify the permitted behavior without making existing code
undefined (this would probably involve making the C++ standard
"module-aware", which, I gather, is under discussion)

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Tue, 26 Oct 2004 02:46:02 GMT
Raw View
John Max Skaller wrote:
> In other words the tradeoff for 'this' might sensibly
> be different. I'm not saying it is, just that it could be.
> Two other pointers -- SP and PC -- do get special treatment,
> why not 'this'?

Well, SP and PC are not visible at the C++ language level,
and neither is the frame pointer, which is the other typical
special register.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Tue, 26 Oct 2004 02:45:43 GMT
Raw View
John Nagle wrote:
>    Even Strostrup says that "this" should have been a reference.
> "delete(this)" is a bad legacy concept from early versions of
> C++.

delete(this) is used by objects which maintain their own lifetime.
It is a widely used idiom, not a legacy concept.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Nicola.Musatti@ObjectWay.it (Nicola Musatti)
Date: Tue, 26 Oct 2004 21:44:31 GMT
Raw View
hyrosen@mail.com (Hyman Rosen) wrote in message news:<1098711734.622021@master.nyc.kbcfp.com>...
> John Max Skaller wrote:
> > In particular, it makes sense to use a machine register
> > for the 'this' pointer on some machines. And it may
> > be the register needs to be saved and restored.
> >
> > AND it may also be doing that requires the register to
> > contain a valid address.
>
> The problem with this argument is that it applies equally
> to any other pointer. Suppose I have the following code:
>
>      struct a {
>          char *p;
>          a() { p = new char; b(); }
>          b() { delete p; }
>      };
>
> It's perfectly plausible that a() would have p in a register,
> that b() would as well, and that a() might try to reload that
> register once b() returned. So there's no difference whether
> b() does 'delete p;' or 'delete this;'; if registers are a
> problem, it's up to the implementation to make things work
> properly.

Where is the problem? 'delete this;' makes a pointer invalid at the
C++ program semantics level. Unless freed memory pages are actually
returned to the OS, I would expect a deleted pointer to remain
perfectly valid at the processor level.

Cheers,
Nicola Musatti

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Wed, 27 Oct 2004 00:20:14 GMT
Raw View
Nicola Musatti wrote:
> Unless freed memory pages are actually returned to the OS,
 > I would expect a deleted pointer to remain perfectly valid
 > at the processor level.

And why do you think that freed pages would not be returned
to the OS? Intel processors did not allow segement registers
to be loaded with invalid addresses. This is the reason that
the C++ standard is so draconian about not allowing anything
to be done with invalid pointers.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: skaller@nospam.com.au ("John Max Skaller")
Date: Wed, 27 Oct 2004 16:33:49 GMT
Raw View
On Mon, 25 Oct 2004 23:56:16 +0000, johnchx wrote:

> How can I suppose that?
>
> If by "a C++ implementation" you mean "a standard-conforming C++
> implementation," then it cannot have the semantics you describe.

> Perhaps what you mean is that the C++ standard ought to be amended to
> permit this.

It seems useful to consider what could be done in the Standard
to provide better support for dynamic loading.

It isn't clear you're entirely right about what's conforming.
I don't see that a compiler fails to conform just because
it supports dynamic loading. It may well be that, in this case,
the behaviour is undefined, but that isn't the same as the
compiler being non-conforming.

That the behaviour is undefined once the programmer ventures
outside the semantics required by the Standard is actually
the problem -- it would be nice to make dynamic loading
available 'more portably'. AFAICS nothing in the Standard
precludes 'lazy' loading of code, in fact it should
work just fine provided the 'as if' rule is met. After all,
the implementor is entitled to specify how code is loaded
and linked.

To actually specify the behaviour, it may be necessary
to get pedantic about things like 'delete this' --
it may seem obvious this executes code for some classes,
but what about a class with a trivial destructor?

How about if some destructors actually got inlined at the
point of call .. so that the code was in the mainline,
not the DLL for some cases?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: skaller@nospam.com.au ("John Max Skaller")
Date: Wed, 27 Oct 2004 16:33:59 GMT
Raw View
On Mon, 25 Oct 2004 19:59:07 +0000, Hyman Rosen wrote:

> John Nagle wrote:
>>    Suppose you have an C++ implementation that manages
>> DLLs (or some other platform-dependent form of "big
>> objects) by keeping a count of the number of instances
>> of the classes implemented in the DLL.  The count goes
>> up for "new", and down for "delete".  When the instance
>> count goes to 0, the DLL is released.
>
> This cannot work well in general.

Right. So, can you propose a scheme which

(a) is a bit more general (covers more cases)
(b) describes the constraints on its usage clearly

I'd be very interested in this.

Being able to load and unload code in some situations,
such as a web server, is vital (they're long running and
you can't afford to accumulate unbounded code space).

Another obvious use is a long running server that actually
generates and then executes DLLs on the fly.

I'd very much like to do this. I don't need it to
work universally -- constraints are OK as long as
I know what they are and they're managable.

For my application, I'm generating the code, so I have
considerable control. I can promise no user static data for example,
except perhaps C strings. I can probably ensure globals
like 'cout' are instantiated in the mainline not the DLL.
I can probably force STL containers to use a custom allocator.

But I don't really have any idea how to do it sensibly.
Perhaps in trying to figure that out, we may discover that
real implementations do things which might be proposed as
extensions to the Standard.

I believe Pete Becker was working on this topic before
the Sydney meeting. Can anyone report here any conclusions?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: skaller@nospam.com.au ("John Max Skaller")
Date: Wed, 27 Oct 2004 16:34:38 GMT
Raw View
On Tue, 26 Oct 2004 02:45:43 +0000, Hyman Rosen wrote:

> John Nagle wrote:
>>    Even Strostrup says that "this" should have been a reference.
>> "delete(this)" is a bad legacy concept from early versions of
>> C++.
>
> delete(this) is used by objects which maintain their own lifetime.
> It is a widely used idiom, not a legacy concept.

Yes indeed but this doesn't mean there could not
be some constraints on it. For example consider this example:

struct X { ...
 void foo() {
    delete this;
  --something_global;
 }
};

Compare it with this foo:

 void foo() {
  --something_global;
  delete this;
 }

Notice very carefully .. in this case the delete this
is the very last thing in the function.

We could *mandate* that delete this had to be last.

If you've done any functional programming you'll immediately
see why this is good. Delete this invokes the destuctor.
In the first foo, the destructor is called, and then,
the function foo returns, but not before
popping registers off the stack that were caller-save.

If the compiler is a bit stupid .. that may include the this
pointer (invalid segment could happen in dynamic loading
scenario).

But in the second case .. using *exactly* the required
syntax, the compiler can be *required* to recognize
that this is a tail call. So there is no need to save
any registers .. and no need then to pop an invalid one
before returning.

OK, this is far fetched .. but the tail call optimisation
is actually vital for performance of many codes, and in
this kind of case it might be possible to gain performance
without loss of much functionality -- you can delete
this but you have to do it last, you can't do anything
else afterwards in the function, not even if that something
doesn't refer to the object data.

With that constraint, you can guarrantee not only that
no data is used from the object .. but also no
code or static data in a DLL is refered to, and require
that the compiler support this case, even for dynamic
loading with automatic unloading .. it might be harder
to ensure otherwise.

Yes this is just wild speculation :)

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: skaller@nospam.com.au ("John Max Skaller")
Date: Wed, 27 Oct 2004 18:42:27 GMT
Raw View
On Mon, 25 Oct 2004 18:52:01 +0000, John Nagle wrote:


>     No, the problem is "delete this" because of when the
> deletion takes place.
>
>     Suppose you have an C++ implementation that manages
> DLLs (or some other platform-dependent form of "big
> objects) by keeping a count of the number of instances
> of the classes implemented in the DLL.  The count goes
> up for "new", and down for "delete".  When the instance
> count goes to 0, the DLL is released.

I don't have to 'suppose' that, the Felix dynlink mechanism
actually does something more or less equivalent, but
it only works for heap allocated function objects... :(

>     For that case, "delete p" is fine, because control is
> outside the class, but "delete this" is not, because
> control is inside the class.  The code will be deleted
> while still being executed, and the program will fault.

I wish I could see a way to actually maintain the count
you speak of for more cases than just function objects:
in particular, the function objects only work because
they're always heap allocated. Other types .. like
a standard library type .. may have virtual methods or
refer to static storage, but I can't modify them.

Perhaps for standard containers, custom allocators
might help.. but i can't see how this can propagate.
If you have a stack allocated struct, with a component
into which a DLL created value is stored, how can you
keep track of it if you didn't write the code for it?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Nicola.Musatti@ObjectWay.it (Nicola Musatti)
Date: Wed, 27 Oct 2004 18:44:22 GMT
Raw View
hyrosen@mail.com (Hyman Rosen) wrote in message news:<1098827847.141927@master.nyc.kbcfp.com>...
[...]
> And why do you think that freed pages would not be returned
> to the OS?

It's not something I know for sure, I only expect this to be the most
common case. In order to relinquish memory pages a memory manager
would have to check at every delete/free whether a complete page was
freed, give it up and readjust its free list. Is it really worth the
effort? How many implementations actually do it? How many
implementations that do it actually run on platforms on which loading
an invalid address in a register causes a trap?

Cheers,
Nicola Musatti

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: skaller@nospam.com.au ("John Max Skaller")
Date: Wed, 27 Oct 2004 18:42:27 GMT
Raw View
On Mon, 25 Oct 2004 16:11:59 +0000, johnchx wrote:

> Or would it be well-defined as is, but become undefined if we made f()
> a member of foo, replacing pf with the implicit this pointer
> parameter?  Do we really want to create a rule that says that a member
> function can't accomplish what a non-member function could?

Of course we 'really don't want to' but it may be good
all the same, if the consequence is that the member
could execute faster. Then you could choose the member
when possible for speed, and the global when the constraints
needed for the member were not met.

Again I'm NOT saying this is the case, just pointing out
that sometimes there are reasons for applying seemingly
pointless constraints. In practice I think compiler vendors
are the best people to advise us of missed optimisation
opportunities (and programmers to judge if they're important
enough to live with the consequences of enabling them).

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Wed, 27 Oct 2004 20:21:54 GMT
Raw View
Nicola Musatti wrote:
 > In order to relinquish memory pages a memory manager would have to
 > check at every delete/free whether a complete page was freed

Ah, but what if the free is of a large area that itself spans a
page or more?

> How many implementations actually do it?

I believe gcc comes with a memory manager which uses memmap for
large allocations. Freeing those instantly returns pages to the OS.

> How many implementations that do it actually run on platforms on
 > which loading an invalid address in a register causes a trap?

Presumably on any of those platforms which run Linux or BSD.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: johnchx2@yahoo.com (johnchx)
Date: Thu, 28 Oct 2004 01:07:20 GMT
Raw View
skaller@nospam.com.au ("John Max Skaller") wrote
> johnchx wrote:
> > nagle@animats.com (John Nagle) wrote
> > >     Suppose you have an C++ implementation that manages
> > > DLLs (or some other platform-dependent form of "big
> > > objects) by keeping a count of the number of instances
> > > of the classes implemented in the DLL.  The count goes
> > > up for "new", and down for "delete".  When the instance
> > > count goes to 0, the DLL is released.
> >
> > How can I suppose that?
> >
> > If by "a C++ implementation" you mean "a standard-conforming C++
> > implementation," then it cannot have the semantics you describe.
> >
> > Perhaps what you mean is that the C++ standard ought to be amended to
> > permit this.
>
> It seems useful to consider what could be done in the Standard
> to provide better support for dynamic loading.
>

Agreed.

> It isn't clear you're entirely right about what's conforming.
> I don't see that a compiler fails to conform just because
> it supports dynamic loading.

That's not what I meant. I meant that the specific *unloading*
semantics that were described (unloading the DLL at the end of the
lifetime of the last class instance) would not be conforming.

> It may well be that, in this case,
> the behaviour is undefined, but that isn't the same as the
> compiler being non-conforming.

The problem is that the described semantics break perfectly
*well-defined* C++ code.

> AFAICS nothing in the Standard
> precludes 'lazy' loading of code, in fact it should
> work just fine provided the 'as if' rule is met. After all,
> the implementor is entitled to specify how code is loaded
> and linked.

Agreed.  The problem, again, is the that the unloading semantics that
were described violate the as-if rule by crashing perfectly legal
programs.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Thu, 28 Oct 2004 11:12:55 GMT
Raw View
John Max Skaller wrote:
> But I don't really have any idea how to do it sensibly.

Garbage collection, naturally. You use the current PC, all
saved PCs on the stack, and all reachable function pointers.
If none of them point into the code of a DLL, it can be
removed from memory.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: skaller@nospam.com.au ("John Max Skaller")
Date: Thu, 28 Oct 2004 16:31:52 GMT
Raw View
On Thu, 28 Oct 2004 11:12:55 +0000, Hyman Rosen wrote:

> John Max Skaller wrote:
>> But I don't really have any idea how to do it sensibly.
>
> Garbage collection, naturally.

That seems correct .. but:

 You use the current PC, all
> saved PCs on the stack, and all reachable function pointers.
> If none of them point into the code of a DLL, it can be
> removed from memory.

That clearly isn't. What if there is a pointer to some
static data, for example a null terminated string?

What about if you copied a polymorphic object created
by DLL code .. that would contain a vtable pointer
into the DLL.

I guess you could extend the garbage collection idea
to cover *all* pointers -- provided RTTI and vtables,
EH tables, etc, didn't contain any encoded adresses
that would fool the collector.

One can consider just using Boehm-Reiser with some changes
to take dynamic loading into account .. I actually asked
Hans Boehm about this and he didn't seem too hopeful it
could work (at least with current compilers and Standard).

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: skaller@nospam.com.au ("John Max Skaller")
Date: Tue, 19 Oct 2004 06:27:32 GMT
Raw View
On Tue, 12 Oct 2004 16:59:19 +0000, John Nagle wrote:

> Max Polk wrote:
>> There's a long history behind object code associated with a function
>> being static as it sits in memory, and that it exists independent of
>> objects, i.e., one copy for all object instances, even if there are no
>> objects.

>      Most systems have at least "shared objects", or "DLLs".  There
> are "big object" systems like CORBA and DCOM.

I'm not sure that's the main problem (although it may be related).

The C notion of 'function' is theoretical nonsense, and doesn't
work in practice either. To make the 'code' of a function work,
it needs an associated environment. Together, the code and
environment are called a closure.

Some examples of closures are: a non-static method together
with a 'this' pointer, a callback in a Unix environment,
which almost always consists of a C function pointer and a
client data pointer, and a function pointer on a Win 3.1 system,
which consists of a code pointer plus a data segment
(implemented with a thunk)

In a simple flat von Neumann machine, the outermost
functions all have the same data pointer, so you can dispense
with it, and C has, because it was designed for such machines.

However, you run into all kinds of problems doing anything
more interesting -- threading, objects, functional programming,
etc, all require you to take *closures* as fundamental.

What this means for distributed systems is that it isn't
enough just to move the code of a function. You have to move
its environment too.

A simple and obvious example:

static int x = 1;
int f() { return x; }

It makes no sense to just move 'return x' as the body of f.
You have to move a closure, which includes 'x' as well.

Moving code is quite easy in theory -- almost trivial if
you have a bytecode compiler. Moving *closures* isn't
quite so simple :)

I would guess that to do this properly you need something
like a way to serialise both code and data AND you have
to have a distributed garbage collector as well.

In other words I wouldn't worry about 'delete this'.
You can probably write distributed systems using C++,
but C++ isn't designed with this in mind, and it will
always be a painful experience.

If mobility is a prime concern, you need a language more suited to it,
perhaps Erlang for example. It's doubtful whether you can even sensibly
retrofit garbage collection to C++, let alone support
transparent closure mobility. It's very *very* difficult to
simultaneously support modern techniques and also provide extensive
backward compatibility. C++ is probably the best possible attempt at finding
a compromise between these two positions.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: stefan_heinzmann@yahoo.com (Stefan Heinzmann)
Date: Tue, 19 Oct 2004 19:50:16 GMT
Raw View
Max Polk wrote:
> There's a long history behind object code associated with a function
> being static as it sits in memory, and that it exists independent of
> objects, i.e., one copy for all object instances, even if there are no
> objects.
>
> We can "delete this" and compare function pointers to determine function
> equivalence to take advantage of this secret knowledge.
>
> A creative new computer architecture which allows migration of
> executable code in and out of existence, such as across machine
> boundaries or for limited-resource mobile devices, could be invented to
> delete the object code itself when the object is deleted.  Or maybe for
> parallel processing you ship an object and it's code off to a tiny
> parallel processing unit.
>
> These could not tolerate a function continuing to execute after the
> object is destroyed, i.e., "delete this".
>
> So is function object code being static and independent of objects an
> implementation detail upon which we should not depend?  Or is it
> actually required?

AFAIK there's no requirement in C++ that the this pointer point to a
valid object throughout the entire execution of a non-static member
function. For example, you could delete this and continue with more
work, provided you refrain from accessing any data members in the code
that follows.

So, yes, the C++ definition seems to imply that the code is always
there, no matter whether object instances exist or not. However, you're
free to do whatever you want as long as you maintain the illusion that
the code is always there. For example, a virtual memory system maintains
the illusion that the code is in main memory although it may be in a
swap file.

For a distributed system, you would have to keep track behind the scenes
which code belongs to what class types, and load it on demand.

So the answer probably is: Your system has to provide the illusion of
static code, but that doesn't mean that it can't be moved around behind
the scenes.

--
Cheers
Stefan

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: ron@sensor.com (Ron Natalie)
Date: Wed, 20 Oct 2004 00:46:59 GMT
Raw View
> AFAIK there's no requirement in C++ that the this pointer point to a
> valid object throughout the entire execution of a non-static member
> function. For example, you could delete this and continue with more
> work, provided you refrain from accessing any data members in the code
> that follows.

This is a gray area.   Actually, the standard doesn't describe the behavior
of an object's lifetime ending during the execution of a non-static member.
Hence it is UNDEFINED BEHAVIOR.   The conventional wisdom says that as long
as you don't touch the "this" pointer explicitly or implicitly (i.e., accessing
a non-static member in the current object), you're OK.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: johnchx2@yahoo.com (johnchx)
Date: Wed, 20 Oct 2004 12:29:46 GMT
Raw View
ux9i003@yahoo.com (Max Polk) wrote
> A creative new computer architecture which allows migration of executable code
> in and out of existence, such as across machine boundaries or for
> limited-resource mobile devices, could be invented to delete the object code
> itself when the object is deleted.  Or maybe for parallel processing you ship
> an object and it's code off to a tiny parallel processing unit.
>
> These could not tolerate a function continuing to execute after the object is
> destroyed, i.e., "delete this".
>
> So is function object code being static and independent of objects an
> implementation detail upon which we should not depend?  Or is it actually
> required?

I don't believe that it is required as such, but there are other
requirements that are probably met most easily by following the
traditional loading-and-execution model.

The example you give, a non-static member function being unable to
continue after "delete this;", would be non-conforming.  The following
program "should work" on a conforming implementation:

#include <iostream>

struct foo {
  void do_something()
  {
     delete this;
     std::cout << "bye!" << std::endl;
  }
};

int main() {
  foo* pf = new foo;
  pf->do_something();
}

This works because the statement following "delete this;" does not
depend on the properties of *pf (whose lifetime has ended), so its
behavior is well defined.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Thu, 21 Oct 2004 01:56:09 GMT
Raw View
Ron Natalie wrote:
> This is a gray area.   Actually, the standard doesn't describe the behavior
> of an object's lifetime ending during the execution of a non-static member.
> Hence it is UNDEFINED BEHAVIOR.

I emphatically disagree. Member functions are not part of an object.
As described in 9.3.2/1, a member function has access to the object
for which it was called through the 'this' pointer. As described in
9.3.1/2, access to unadorned members of the object are transformed
into expressions using 'this'. Since member functions ar in no way
associated with a specific object, there is no reason to say that
ending the lifetime of a particular object causes undefined behavior
during the execution of a member function. It is simply the case that
if the lifetime of the object referred to by 'this' has ended, then
the same rules apply as for any other pointer.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: ux9i003@yahoo.com (Max Polk)
Date: Tue, 12 Oct 2004 16:13:34 GMT
Raw View
There's a long history behind object code associated with a function being
static as it sits in memory, and that it exists independent of objects, i.e.,
one copy for all object instances, even if there are no objects.

We can "delete this" and compare function pointers to determine function
equivalence to take advantage of this secret knowledge.

A creative new computer architecture which allows migration of executable code
in and out of existence, such as across machine boundaries or for
limited-resource mobile devices, could be invented to delete the object code
itself when the object is deleted.  Or maybe for parallel processing you ship
an object and it's code off to a tiny parallel processing unit.

These could not tolerate a function continuing to execute after the object is
destroyed, i.e., "delete this".

So is function object code being static and independent of objects an
implementation detail upon which we should not depend?  Or is it actually
required?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: nagle@animats.com (John Nagle)
Date: Tue, 12 Oct 2004 16:59:19 GMT
Raw View
Max Polk wrote:
> There's a long history behind object code associated with a function
> being static as it sits in memory, and that it exists independent of
> objects, i.e., one copy for all object instances, even if there are no
> objects.

     While this seems more suited to Java, where code object are
something you can talk about in the language, there's an issue
here for C++.

     Most systems have at least "shared objects", or "DLLs".  There
are "big object" systems like CORBA and DCOM.  C++ is used with
all of these, but (especially in the Microsoft world) there
are language extensions to support them, or external interface
languages.  More support for such things might be useful.

     Right now, the only "externally callable interface" defined
for C++ is "main()".

        John Nagle

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]