VC++ extension

Alex Martelli alex at magenta.com
Thu Aug 10 04:06:54 EDT 2000


"Courageous" <jkraska1 at san.rr.com> wrote in message
news:3992013C.3AA0CA92 at san.rr.com...
>
> > > This is because the designers
> > > of C++, in Their Equally Infinite Wisdom (R), ah, well....
> > > nevermind. Trust me, they biffed it.
> >
> > Sorry - I dont trust you.  Please explain, ensuring that you take into
> > consideration that a level of link-time type-safety was a goal...  And
> > also the fact that it is only an issue for interfacing with C - if
> > everyone got modern, there would be no issue here, either <wink>
>
> The designers biffed it, because they failed to design link-level
> compatability. This is a manycolored problem; a symbol name mangling
> standard would have been a good first step.

<sarcasm level='mild'>
The designers of C++ (and those of all other languages I'm aware of)
failed to design right into their languages a way to end world hunger,
cure HIV, and brew a good cup of coffee, too.  Do you also count
these as instances of "biffing"?
</sarcasm>

"Link-level compatibility" is an issue that just CANNOT be solved in
a totally portable, cross-platform way, *for a language which is intended
to allow direct compilation into optimized binary code*.  And FAKING
it via "symbol name mangling standards" would be a horrible mistake,
when the uniformly-named binaries don't really interoperate AT ALL.

Name *ONE* language which allows such compilation AND ensures
at the language-standard level ANY level of "link-level compatibility",
without impeding development of a new compiler for any machine...?!

For example, C does *not*.  It fails to specify enough detail as to how
structures are laid out in memory -- how COULD it possibly do so in
a way that allows optimized performance on byte-addressed machines
with OR without alignment constraints, non-byte-addressed ones, etc?
AND specify it portably?!  It does not specify calling conventions --
which arguments go into which registers, which ones go where in the
stack, etc -- how could it POSSIBLY do so, portably, across a range
of machines that have utterly different concepts of registers (named,
numbered, none at all, windowed, ...?!), stacks (ditto), and anything
else you can possibly think of?!

Ada, Eiffel, Sather, C, Fortran, Cobol - you name it, it just can't solve
these issues.  They're _inherently_ insoluble, can't you see?!  Therefore,
accusing the designers of any of these languages of "biffing" because of
not having solved an insoluble problem is -- well -- words fail me.  I just
hope that, when your software designs fail to solve insoluble problems,
you are judged as harshly as you dare judge other software designers.

But let's consider specifically the "symbol name mangling standard" you
desire.  Have you read Stroustrup's "Design and Evolution of the C++
Programming Language"?  Apparently not, because he explains the
issues so clearly.  One: C++ has, as a design objective, that of allowing
operation with existing system linkers (absolutely crucial: on many
machines,
user-level software just *cannot* replace the system-linker; have you ever
worked with mainframes...?).  What can it know about the allowed char
set for linker-names?  Answer: next to nothing.  What characters are
allowed or disallowed in linker-seen names?  What identifier length?
What other constraints?  There is just no way to specify this without
cutting C++ out of the possibility of operating with system linkers on
some important machines.

Two: suppose one WAS willing to say "this language will never run on
any machine whose system-linker doesn't support unlimited identifier
length and the characters @ ~ ! $ % as part of linker-identifiers" (a
huge price).  What would the benefit be of forcing one name-mangling
*for functions that are NOT going to interoperate anyway* because
they use different calling-conventions, structure layouts, etc?!  See above
re the reasons that make such differences unavoidable.  The "good first
step" you desire would just let errors emerge as crashes at runtime
*systematically*, rather than ALLOWING the linker to catch SOME
such errors (not all -- no way to specify that either) by name-mismatch.

E.g. consider two compilers on Win/NT.  One of them chooses to use
the __fastcall calling convention supported by the linker, placing some
arguments in certain registers; the other one chooses to use the
__stdcall convention instead, placing all arguments in stack (callee-
frees-stack).  I have a library/objectfile from compiler A defining a
function int foo(int), and I'd love to call it from compiler B (clearly an
impossibility due to calling-convention mismatch).  Would you force
both compilers to call the function _int_foo_int, say?  Then the link would
LOOK like it succeeded, and we'd have a crash at runtime in the call
(since callee would free a piece of stack that caller never allocated).

MUCH better, clearly, to at least ALLOW the compilers to follow the
platform naming conventions, using __foo_i as the __fastcall function
name and _foo at 4 as the __sdtcall function name.  This way, at least,
the incompatibility is detected at link-time -- MUCH cheaper than a
test and a runtime crash.  So much for "good first steps".


The only way around the platform-incompatibility issues that will never
allow linkage compatibility on all platforms is, in practice, to specify the
platform itself.  This leads to the Java path -- a virtual machine that
does not really reflect the underlying platform, specified as the one and
only allowed compilation-target.  That, of course, does not allow any
interoperation with existing software (libraries, OS, ...) on each given
platform, which IS a key design goal for C++ (it is to be a system-level
language, "a better C than C").  "Biffed", _indeed_.


Alex






More information about the Python-list mailing list