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