Randy said:
(e-mail address removed) wrote
(in article
Hmm. The language guarantees that an int will be an int, and
you probably believe that. The language guarantees the behavior
for global variables, and you do not believe it. Why?
I think the O.P. has something else in mind. He's
got a global variable `foo_count' but he cannot write a
static initializer for it: it's a quantity that gets
computed from information that only becomes available at
run-time. Somewhere there's a foo_initialize() function
that sets up the foo subsystem, setting `foo_count' and
presumably building other data structures as well. The
guaranteed initialization to zero takes place as it should,
but that initialization doesn't produce a useful value.
Now imagine that the program is such that foo_initialize()
doesn't get called unconditionally during startup; it's
expensive, and only gets called if some other part of the
program decides to make use of the foo facilities. In some
perfectly good program runs, foo_initialize() may never be
called at all, and `foo_count' will remain zero the whole time.
The O.P. (I think) fears that some piece of sloppy code
somewhere in a remote and dusty corner may be using `foo_count'
without checking to see whether foo_initialize() needs to be
called first. He's looking for ways to catch this code in
the act, so he can identify it and repair it.
People have mentioned various outside-of-C approaches,
like changing the access permissions on `foo_count's memory
page, or using debuggers that can set watchpoints. These are
fine as far as they go, but they only go as far as the test
plan will take them: They'll find the bad `foo_count' uses
that actually occur in the test scenarios, but you're left
with the nagging possibility that the scenarios leave some
execution paths uncovered.
I fear this is one of those cases where the disadvantages
of global variables show themselves. Perhaps the O.P. might
consider hiding `foo_count' by making it static, and writing
a get_foo_count() function to retrieve its value (he might
also write set_foo_count(), if that's appropriate). These
functions could easily be made to squawk if invoked before
foo_initialize(), eliminating the need for the memory-access
tricks and fancy debuggers. If it makes sense, they could
even be made to call foo_initialize() themselves, if need be.
If there are more than a few global variables in the foo
subsystem, it might make sense to gather them all into a
static struct and write
struct foo_context *get_foo_context(void);
instead of writing individual accessors for each variable.
This should also placate all but the most fanatical worshipers
of the Little Tin God, since once a client has retrieved the
context pointer no further function-call overhead is incurred.
(Anyone who starts complaining about the inefficiency of
pointer dereference is a fanatical LTG worshiper, and should
consider joining a twelve-step group.)