Topic: Portability. Modules. WAS: Are all Windows programs
Author: JdeBP@jba.co.uk (Jonathan de Boyne Pollard)
Date: 1996/02/26 Raw View
Eugene Lazutkin (INT@msn.com) wrote:
| On Tuesday, February 13, 1996 9:51 AM, JdeBP@jba.co.uk
| (Jonathan de Boyne Pollard) wrote:
| > Again, this is not in fact true, and part of the problem that the original
| > poster was pointing out. The startup code in most Windows compilers calls
| > WinMain directly. There is no `main' function anywhere in the program at
| > all.
|
| I don't care about the actual implementation. Virtually there is a main().
Wrong. There is *no* `main', and this is the problem.
| Almost all platforms call some stub before your main().
Again, this is not true. `main' doesn't even have to be a function at all.
All that is demanded is that the start of the program, *as it appears to the
programmer in the C++ language source*, is a function called `main'. The
implementation is perfectly free to recognise a definition of the `main'
function, and to do whatever is necessary to ensure that the program
"starts" with that function.
For instance, instead of emitting a symbol definition and a function
prologue into the object file, the a C++ implementation is free to emit the
C++ runtime initialisation code in place of a function prologue, and have
it fall through directly into the body of `main'. As long as `return', the
arguments to `main', and exception processing appear just as they should
for a real function, the implementation is free to do as it wishes.
| > | BTW, the same can be applied to the Unix (MacOS) platform. X-based
| > | (Motif-based, Fresco-based,...) program are not portable either unless
| > | you have the specific GUI implementation for your target platforms.
| >
| > Not so. If we are expanding the discussion to other platforms, you will
| > find that many other platforms do not demand that programs be ill-formed
| > (as a program lacking any definition of `main' surely is).
|
| You can call a main() from the WinMain().
But you cannot compile
int main ( int, char ** ) { return 0 ; }
. Again, you are not quite getting it. If the implementation *requires*
you to define a `WinMain', and makes `main' optional then this is the
reverse of the language definition, where `main' is required and `LibMain'
(and indeed any other function) is optional.
| > I don't remember about X offhand, but OS/2 Presentation Manager does not
| > require non-standard startup procedures. The PM API is, as far as the
| > applications programmer is concerned, just another function library in a
| > DLL, and OS/2 PM programs start with `int main(int, char **)' just the same
| > as text-mode programs do.
|
| I still think that PM API makes programs unportable.
Try reading the next pert of my original message :
| > And *this* is the issue at hand, not whether the APIs are portable. Most
| > APIs appear as "just another function library" to the applications
| > programmer, and portability or otherwise of libraries is not an issue with
| > the C++ language itself. The issue with the C++ language is that `main' is
| > the defined start procedure of *any* C++ program (sauf constructors of
| > objects at global namespace scope with static storage duration), and
| > Windows programs are *forced* to *not* use `main'.
|
| IMHO, C++ language doesn't care about the name of functions.
Well in this case YHO is wrong. The C++ standard is specific about one
particular function, denoted `main'.
| > Of course, as I've said before, the simple solution is to fix
| > [basic.start.main] to allow
| >
| > int main ( HINSTANCE, HINSTANCE, char *, int ) { /*...*/ }
| >
| > as a legal definition of `main' (my proposal is for the implementation to
| > define a set of legal function types for the definition of `main', which at
| > minimum must contain `int main()' and `int main(int, char**)'). Then
| > compiler vendors targetting DOS+Windows who wish to claim conformance can do
| > so by allowing their compilers to recognise the above function definition.
|
| I'm not a pro in a standardization, but I think that this solution
| looks like a patch for MS Windows(TM). What if totally graphical
| environment doesn't support any parameters or these parameters aren't a
| text? This is a Unix heritage (and useful one :-) ). What does
| HINSTANCE mean for ABCDOS? What if all this four parameters don't make
| any sense at all for particular OS? E.g., Win32 doesn't use the second
| HINSTANCE. I don't speak about future OSes.
You didn't read the whole paragraph. Read it again. My proposal is that
implementations can define a set of legal function types that they will
accept in a program for the definition of `main', with the one restriction
that `int main()' and `int main(int, char **)' be members of that set.
This allows Windows implementations to state that (in addition to the
compulsory two definitions) they will accept a definition of `main' as
given above, and other implementations with similar requirements to allow
whatever function definition of `main' makes their environment happy also.
This is known as meeting the problem halfway. Currently, the C++ (draft)
standard is both self-contraditory and restricted to UNIX-lookalike startup
semantics. Currently, Windows C++ implementations would not conform to the
standard (were the drafts as they stand made into a standard). If Windows
C++ implementations switch to using `main', and if the C++ standard is
modified (and corrected) as I've suggested, then Windows (and other) C++
implementations will be able to conform in this area.
---
[ To submit articles: Try just posting with your newsreader. If that fails,
use mailto:std-c++@ncar.ucar.edu
FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html
Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: "Eugene Lazutkin" <INT@msn.com>
Date: 1996/02/20 Raw View
On Tuesday, February 13, 1996 7:48 AM,
James Kanze US/ESC 60/3/141 #40763 <kanze@lts.sel.alcatel.de> wrote:
> In article <01BAF61B.3131B100@dino.int.com> Eugene Lazutkin
> <eugene@int.com> writes:
>
> |> On Tuesday, February 06, 1996 9:18 PM,
> |> rich@kastle.com (Richard Krehbiel) wrote:
>
> [...]
> |> Another point of non-portability is #pragmas. Static containers are
> |> almost useless unless you can specify the order of their
> |> construction/destruction.
>
> This depends on the design of the container. See below for two ways
> of handling this.
>
> |> Borland provides you with #pragma
> |> startup/exit (am I correct with names?). With this tool you can specify
> |> a priority. It is not a ultimate medicine but it helps a lot!
>
> It helps make your programs non-portable, you mean:-) (as you point
> out). There are better solutions.
I don't like this solution either. But it works. See below.
> The oldest one, rarely used except for the simplest cases today, is to
> design the list such that the initial initialization to 0 is adequate,
> and give it a special no-op constructor. Thus, for example, my
> command line parser class maintains a list of options (staticly
> declared objects); a NULL pointer signifies an empty list, and the
> constructor does nothing. Thus, it doesn't matter if the options are
> constructed (and register themselves) before the list.
It doesn't help to create a simple double-linked ring. Not all
containers can be built on a single-linked list or a tree structure.
E.g., any member of a double linked ring can exclude itself from the
list automatically by its destructor at any time. You can't do it
with single-linked list or with double-linked list (not ring).
BTW, who frees the allocated memory? When? How can I specify the
order of destruction? ObjectSpace's STL has problems with that.
The program using this STL will leak. They can't eleminate this
problem. OK, they have a work around. But it is very inefficient:
they use per-object allocators instead of per-class.
> The more frequent solution today is to have a function returning a
> reference to a local static object. The object will be constructed
> the first time the function is called. The enrolment functions in the
> Item's call the function to get the actual list object.
Does this static object have any constructors? Or its components?
Is it based on some class without constructors? If not, who will
be initialize it? And how? Who will deinitialize it? A lot of
problems.
Of course, both these solutions work just fine in certain specific
cases. But it is not a generic answer. It is a trick.
> I often encapsulate the above solution in a SharedList interface
> class. All instances of the SharedList actually refer to the same
> list object. The SharedList only contains a pointer to the actual
> list object, and forwards all requests to it. The pointer is
> initialized by calling the function above in the constructor.
>
> |> Alternative way: include all items into the container manually and
> |> don't forget to do this initialization every time when you use this
> |> container in your program.
>
> This is extremely error prone (as you also point out). If you are
> willing to accept that all of the objects are known in the same
> compilation unit, you might as well define them there, and let the
> guaranteed order of construction within the compilation unit do the
> trick.
This is C++, not Pascal. We have separate units. I think it is too
strong requirement to put some logically different items together.
I think it is too error-prone.
Eugene Lazutkin
eugene@int.com
---
[ To submit articles: try just posting with your news-reader.
If that fails, use mailto:std-c++@ncar.ucar.edu
FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html
Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu.
]
Author: "Eugene Lazutkin" <INT@msn.com>
Date: 1996/02/20 Raw View
On Tuesday, February 13, 1996 9:51 AM, JdeBP@jba.co.uk
(Jonathan de Boyne Pollard) wrote:
> Eugene Lazutkin (eugene@int.com) wrote:
> | On Tuesday, February 06, 1996 9:18 PM,
> | About the main() function. A Windows compiler (MS, Borland, Symantec,
> | Watcom) doesn't check its presence. Linker does. It knows the name of
> | an entry point.
>
> Not entirely correct. One of the compilers that you mention (Borland)
> emits additional code when it encounters the definition of `main'. See
> Borland's library source for details.
>
> | You may think that main() is buried in the standard Windows
> | library and it will call WinMain(). That's it, you use the main()
> | implicitly.
>
> Again, this is not in fact true, and part of the problem that the original
> poster was pointing out. The startup code in most Windows compilers calls
> WinMain directly. There is no `main' function anywhere in the program at
> all.
I don't care about the actual implementation. Virtually there is a main().
I know that all my static constructors will be executed BEFORE main(),
WinMain() or any other head procedure. It is important. It doesn't make
any difference for me whether or not main() is the first called subroutine.
In fact, in most cases it is not true. Almost all platforms call some
stub before your main().
> | BTW, the same can be applied to the Unix (MacOS) platform. X-based
> | (Motif-based, Fresco-based,...) program are not portable either unless
> | you have the specific GUI implementation for your target platforms.
>
> Not so. If we are expanding the discussion to other platforms, you will
> find that many other platforms do not demand that programs be ill-formed
> (as a program lacking any definition of `main' surely is).
You can call a main() from the WinMain(). You can put this stub into your
default library. You can ask Bill Gates to do that for all VC++ customers.
Does it make anybody happy? I don't think so. (No offence, but it doesn't
seem to me as an important issue. Maybe MS should change their
implementation?)
> I don't remember about X offhand, but OS/2 Presentation Manager does not
> require non-standard startup procedures. The PM API is, as far as the
> applications programmer is concerned, just another function library in a
> DLL, and OS/2 PM programs start with `int main(int, char **)' just the same
> as text-mode programs do.
I'm happy for OS/2 programmers. I really am! :-) I still think that PM API
makes programs unportable. And the exact signature of the head function
helps a little. I think that the biggest problems will be to map all PM
procedures to their equvalents. From my experience, sometimes you have
to redesign a few important parts of the program. And main() is a minor
issue.
> And *this* is the issue at hand, not whether the APIs are portable. Most
> APIs appear as "just another function library" to the applications
> programmer, and portability or otherwise of libraries is not an issue with
> the C++ language itself. The issue with the C++ language is that `main' is
> the defined start procedure of *any* C++ program (sauf constructors of
> objects at global namespace scope with static storage duration), and
> Windows programs are *forced* to *not* use `main'.
See above. You can do that with less-than-10-lines stub. IMHO, C++ language
doesn't care about the name of functions. But run-time system do. Standard
tries to define the behavior of the active executable environment.
> Of course, as I've said before, the simple solution is to fix
> [basic.start.main] to allow
>
> int main ( HINSTANCE, HINSTANCE, char *, int ) { /*...*/ }
>
> as a legal definition of `main' (my proposal is for the implementation to
> define a set of legal function types for the definition of `main', which at
> minimum must contain `int main()' and `int main(int, char**)'). Then
> compiler vendors targetting DOS+Windows who wish to claim conformance can do
> so by allowing their compilers to recognise the above function definition.
I'm not a pro in a standardization, but I think that this solution
looks like a patch for MS Windows(TM). What if totally graphical
environment doesn't support any parameters or these parameters aren't a
text? This is a Unix heritage (and useful one :-) ). What does
HINSTANCE mean for ABCDOS? What if all this four parameters don't make
any sense at all for particular OS? E.g., Win32 doesn't use the second
HINSTANCE. I don't speak about future OSes.
It seems to me that we can specify the order of execution but we don't have to
dictate the real-world solutions. To me "void main()" works just fine. If
you want to obtain some shell-specific information or OS-specific data,
use custom functions. In simple cases "int main( int, const char** )"
is suitable too.
Eugene Lazutkin
eugene@int.com
---
[ To submit articles: try just posting with your news-reader.
If that fails, use mailto:std-c++@ncar.ucar.edu
FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html
Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu.
]