Detecting Reads of Global Uninitialized Variables

J

jyu.james

I'm trying to detect reads of uninitialized global variables (that are
declared in one file, and used in another as an extern).

I know that ANSI C initializes all global variables to 0, however, I do
not want to rely on this for initialization. Instead, I want to
explicity initialize all variables myself. I've looked at tools like
Compuware BoundsChecker, which does an amazing job in detecting
uninitialized variables, but doesn't detect reads of GLOBAL
uninitialized variables.

Is there a tool out there that can do this? Or is there a particular
technique that can be used to automate this?

James
 
M

Mike Wahler

I'm trying to detect reads of uninitialized global variables (that are
declared in one file, and used in another as an extern).

I know that ANSI C initializes all global variables to 0, however, I do
not want to rely on this for initialization.

Why not? The language guarantees it.
Instead, I want to
explicity initialize all variables myself. I've looked at tools like
Compuware BoundsChecker, which does an amazing job in detecting
uninitialized variables, but doesn't detect reads of GLOBAL
uninitialized variables.

That's because they *are* initialized.
Is there a tool out there that can do this? Or is there a particular
technique that can be used to automate this?

You'll need some kind of C parser.

-Mike
 
A

Alexei A. Frounze

Mike Wahler said:
You'll need some kind of C parser.

If these variables are grouped into a special section, it might be possible
to trap on each and every access to the pages in which the section lies. It
may not be easy to do, though, or not easy to find everything if you have
many variables in there and need to stop every time... Just an idea...

Alex
 
J

Jack Klein

If these variables are grouped into a special section, it might be possible
to trap on each and every access to the pages in which the section lies. It
may not be easy to do, though, or not easy to find everything if you have
many variables in there and need to stop every time... Just an idea...

Alex

To quote "Alexei A. Frounze said:
This is off topic for comp.lang.c.
Alex

I'm having trouble implementing your suggestion on a C program running
on an 8051.

And what does your answer have to do with standard C, which knows
nothing of 'special sections' or 'pages'?
 
J

junky_fellow

I'm trying to detect reads of uninitialized global variables (that are
declared in one file, and used in another as an extern).

I know that ANSI C initializes all global variables to 0, however, I do
not want to rely on this for initialization. Instead, I want to
explicity initialize all variables myself. I've looked at tools like
Compuware BoundsChecker, which does an amazing job in detecting
uninitialized variables, but doesn't detect reads of GLOBAL
uninitialized variables.

Is there a tool out there that can do this? Or is there a particular
technique that can be used to automate this?

The best solution will be to find all such uninitialized global
variables
using some tool (like cscope) and initialize them appropriately
depending on their types.
 
A

Alexei A. Frounze

Jack Klein said:
I'm having trouble implementing your suggestion on a C program running
on an 8051.

And what does your answer have to do with standard C, which knows
nothing of 'special sections' or 'pages'?

Thank you, Jack.
Alex
 
J

jyu.james

Well, the problem is that I expect my code to actually initialize all
the global variables. I want to make sure that I'm not missing any
initializations. I don't want to just go and add artificial
initializations. Basically, I'm just trying to verify that the
existing code does initialize all the variables (before reading from
them).

Any suggestions for that?
 
A

Alexei A. Frounze

Well, the problem is that I expect my code to actually initialize all
the global variables. I want to make sure that I'm not missing any
initializations. I don't want to just go and add artificial
initializations. Basically, I'm just trying to verify that the
existing code does initialize all the variables (before reading from
them).

Any suggestions for that?

Put all those variables into a structure, memset() it to 0. That must make
your code deterministic, even if there must have been something else but 0
in some variable(s).

Alex
 
R

Randy Howard

(e-mail address removed) wrote
(in article
Well, the problem is that I expect my code to actually initialize all
the global variables.

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?
 
J

John Devereux

Randy Howard 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?

There *are* real-life situations where this happens. I have seen this
when bringing up embedded systems, where the startup code or linker
script is incorrect. Also you sometimes want to write hardware or
memory initialisation code, in C, that executes before the C run time
system has been started up. It is usually possible to do this provided
you do not make assumptions about global variables being initialised
properly.
 
R

Randy Howard

John Devereux wrote
(in article said:
There *are* real-life situations where this happens. I have seen this
when bringing up embedded systems, where the startup code or linker
script is incorrect. Also you sometimes want to write hardware or
memory initialisation code, in C, that executes before the C run time
system has been started up. It is usually possible to do this provided
you do not make assumptions about global variables being initialised
properly.

Fair enough. In an embedded situation, the real-world rules are
often different than what the C standard has to say about
things. I didn't see anything to indicate that was the case
here in the original post.
 
E

Eric Sosman

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.)
 
R

Randy Howard

Eric Sosman wrote
(in article said:
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.

That makes a lot of sense, and if that is the concern, then I
retract my early comments.
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.

Yet another reason not to have global variables running around.
With dual-core systems becoming ubiquitious, even if you /want/
to live in the "only by the book standard C" world, you'll be
forced to support threading soon, with or without C, and you'll
learn to avoid them like the plague then.
I fear this is one of those cases where the disadvantages
of global variables show themselves.

Ahh, you beat me to it.
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.

I've done that sort of thing before, it never felt 100% "clean",
but it works.
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.)

:)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top