At 09:40 PM 2/3/00 -0800, Marshall Clow wrote:
> >Part of my difficulty was that I didn't expect the CodeWarrior 
> linker to be as ruthless as it actually is.  When one 
> explicitly specifies that a code module is to be included in a 
> target, I expect the linker to put it in the executable, 
> whether or not anything else actually depends on it.
>
>Here we disagree. The old Think C linker did this. I hated 
>it.  I want _small_ executables.

We don't actually disagree.  CodeWarrior's linker capability is 
clearly valuable; it should just be documented.

>When you say "static initializer", do you mean a global object 
>that contains a constructor?
>(or is initialized to a value) such as:
>
>BytePtr gBar = NULL;
>
>Or do you mean a static object of non-global scope, like this:
>
>void Foo ( ) {
>         static int twelve = 12;
>}
>
>In the second case, the variable "twelve" will not be 
>initialized until the first time that
>Foo () is called.

The term I should have used is "dynamic initialization of a 
non-local object": a variable that is global (or static and 
outside any function), which is initialized by something other 
than a constant.  For example

     AClass x;

where the constructor for AClass has some interesting code, or

     double y = mathFunction(1.0);

In both cases, the initialization code will be executed before 
PilotMain() is entered.


> >Strictly speaking, it is not correct for a C++ linker to use 
> this sort of heuristic: the programmer should be able to 
> specify that a particular module is to be included, exactly 
> *because* he needs the side-effects of a static initializer in 
> that module.
>
>If you include a module that contains global variables, the 
>globals should be included in
>the executable, and all code needed to construct and destruct 
>them as well.
>
>Could you post an example of what you were doing (because I 
>don't think I understand).

Well, my actual example involved calling WinCreateWindow() from 
within the constructor that was called to initialize a global 
variable.  But to illustrate the point about the CodeWarrior 
linker, here's an example (slightly extended for dramatic effect!).

Create a project using C++ stationery (this example uses the 
stock CW 6.0 release, with the PalmOS 3.0 SDK).  Create the 
following file "sub.cpp" and add it to the project:

     #include <Pilot.h>

     class C {
     public:
         C() {
             ErrDisplay("Got here");
         }
     };
     C c;


In the target settings dialog, set global optimizations to level 
2.  Build and execute the application(1).  It will do nothing.

Now add the following function to Starter.cpp, just before PilotMain:

     void f()
     {
         class C;
          extern C c;
          C* pc = &c;
     }

Build the app again and execute it(2).  Nothing happens.

Now add the following lines at the beginning of PilotMain:

     int i = 0;
     if (i) {
         f();
     }

Build the app again and execute it(3).  Again, nothing happens.

Now set the global optimizations level from 2 down to 1.  Build 
the app once more and execute it(4).  This time it displays the 
message "sub.cpp, Line: 6, Got here".

The first time, there was no reference to Sub.cpp from 
Starter.cpp, so the linker did not include Sub.cpp in the 
executable, hence did not perform its dynamic initialization.

The second time, function f() in Starter.cpp referred to a the 
variable c in Sub.cpp.  But since Starter.cpp had no reference to 
f(), the linker didn't include f() in the executable, and 
therefore, not Sub.cpp either.

The third time, PilotMain() had a reference to function f(), but 
the compiler optimized it out, so f() and Sub.cpp were again 
omitted from the executable.

The fourth time, the call to f() was not optimized out, so f() 
was included, and Sub.cpp was included, and the initializer of 
the global variable c was invoked, displaying the message.


-- 
For information on using the Palm Developer Forums, or to unsubscribe, please see 
http://www.palm.com/devzone/mailinglists.html

Reply via email to