Use static variable across multiple files??

R

Robert Crandal

My C++ project consists of multiple C++ files. I have
one file (named "mystatic.cpp") which I have provided
below:

//
// mystatic.cpp
//

static int gValue = 100

void foo()
{
gValue++;
}

Is it possible to allow code from all my other C++ files to
refer to the static "gValue" variable?? I basically want to
use "gValue" as a global static variable, but I'm not sure
how to do this.

thank you
 
A

Alf P. Steinbach

* Robert Crandal:
My C++ project consists of multiple C++ files. I have
one file (named "mystatic.cpp") which I have provided
below:

//
// mystatic.cpp
//

static int gValue = 100

void foo()
{
gValue++;
}

Is it possible to allow code from all my other C++ files to
refer to the static "gValue" variable?? I basically want to
use "gValue" as a global static variable, but I'm not sure
how to do this.

Using the global variable will increase the complexity of your program and add
bugs. That's why C++ makes it the less easy option. And, freed from actively
supporting such global variables, C++ adds things that can go wrong in addition
to the things that can go wrong in general (in other languages); in particular
read up on the C++ "static initialization fiasco" e.g. in the FAQ (a very
popular GUI framework suffers from this, constraining its use severely).

But technically, just remove the "static" from your definition, unless you have
a top level "const", in which case you also need to add "extern".

Then add "extern" to declarations in other translation units.


Cheers & hth.,

- Alf
 
R

Robert Crandal

But technically, just remove the "static" from your definition, unless you
have a top level "const", in which case you also need to add "extern".

Really, I can remove the "static" definition and my global variable will
still "exist" for the duration of my program??

BTW, I know it's usually a bad idea to use global variables, but my
applications always seem to require a collection of "state" variables that
need to exist for the entire duration of my GUI program. In your opinion,
what's a good technique for managing a collection of state variables that
might need to be accessed at any time by another C++ file module?? I
usually just create a small set of unique global variable names...if no
other
variables share the same names I don't see what can go wrong??

thanks for your advice!
 
A

Alf P. Steinbach

* Robert Crandal:
Really, I can remove the "static" definition and my global variable will
still "exist" for the duration of my program??
Yes.


BTW, I know it's usually a bad idea to use global variables, but my
applications always seem to require a collection of "state" variables that
need to exist for the entire duration of my GUI program. In your opinion,
what's a good technique for managing a collection of state variables that
might need to be accessed at any time by another C++ file module??

Start by analyzing the data flows. What piece of the system requires exactly
what information to do its work, and where does it get it from? Draw connecting
arrows representing the data flows and try as best you can to make sure that
absolutely every "process" has /everything/ it needs, and /not more/. To the
degree possible defer decisions as to where data is stored. Many such decisions
will be unavoidable but try. Keep very strongly in mind that a data flow diagram
does generally not map one-to-one to software (this is a main reason to avoid
data storage allocation at this point). The mapping can be intricate.

It's very very old and nowaydays it's my impression it's not much used (the
simplistic version doesn't mesh well with OO), but it will give you a more clear
idea of the requirements and how things really work in your system.

Then design things -- the mapping between data flows, processing and software
-- so as to enforce the data flow directions. This involves deciding where
data should be stored, i.e. who knows about what. Ideally that should be tied to
responsibility and needs, as in an organization of people. 'const' in C++ helps
very much. Using functions to access data instead of global variables is a more
general technique, which also helps to encapsulate things and provide hooks
where tests, other functionality etc. can be attached/inserted.

usually just create a small set of unique global variable names...if no
other
variables share the same names I don't see what can go wrong??

The general problem is that globally available read/write variables provide data
flow connections everywhere, so that any piece of the system can potentially
affect any other piece. You do not know where a change comes from, or when, or
under what conditions what values are guaranteed (if any), i.e. what causes
what. The number of possible causal connections increase as the square of the
number of distinct smallest intended-to-be-understood-on-their-own "modules",
which is unmanagable. It's like a large organization where every employee is
free to modify any of the organization's data to the best (worst) of his/her
ability and perceived local needs. Instead, such access should be tied to what
each employee is responsible for and actually needs.

Good old Edsger Dijkstra touched on this in his classic paper "GOTO considered
harmful", which is available as an "ACM classic" (free).

The data flow spaghetti is the data side of things analog to goto based control
flow spaghetti, just a slightly more indirect way of establishing catastrophic
causal connections.


Cheers & hth.,

- Alf
 
S

SG

My C++ project consists of multiple C++ files.  I have
one file (named "mystatic.cpp") which I have provided
below:

// ...
   static int gValue = 100
// ...

Is it possible to allow code from all my other C++ files to
refer to the static "gValue" variable?? I basically want to
use "gValue" as a global static variable, but I'm not sure
how to do this.

I think you're not aware of the meaning of "static" here. "static" is
a fairly overloaded keyword. Depending on where you put it, it behaves
differently. If you declare variables at global or namespace scope
these variables already have "static storage" no matter what. In this
context the keyword static affects linkage instead. You declared
gValue to have *internal* linkage which is apparently not what you
want. Solution:

/* myglobals.hpp */
extern int gValue;

/* myglobals.cpp */
int gValue = 100;

where myglobals.hpp needs to be included in other translation units so
they can refer to the gValue variable. Without the keyword extern this
would be a definition. So, extern does two things here: It enforces
external linkage (but external linkage is the default for non-const
variables at global scope anyways) and it also turns a definition into
a declaration (in this case). At global scope "extern" is sort of the
opposite of "static".

Cheers,
SG
 
J

Jorgen Grahn

Really, I can remove the "static" definition and my global variable will
still "exist" for the duration of my program??

That's really basic knowledge; if it surprises you, I humbly suggest
you study the language a bit more.
BTW, I know it's usually a bad idea to use global variables,

This might on the other hand be the reason you don't know: you weren't
taught it because it's considered a bad idea. (That in itself is a bad
idea, but never mind.)
but my
applications always seem to require a collection of "state" variables that
need to exist for the entire duration of my GUI program. In your opinion,
what's a good technique for managing a collection of state variables that
might need to be accessed at any time by another C++ file module?? I
usually just create a small set of unique global variable names...if no
other
variables share the same names I don't see what can go wrong??

I can buy that, if you're in a hurry and just need to make it work.
But at least lump all of them in one or a few common structs, so they
are easy to find. "global.foo" is easier to spot than "gFoo".

/Jorgen
 
J

James Kanze

* Robert Crandal:
Using the global variable will increase the complexity of your
program and add bugs. That's why C++ makes it the less easy
option.

Except that it doesn't. Variables defined at namespace scope
(like gValue, above) are global by default; his gValue isn't
global because he's explicitly declared it not to be, by using
the keyword static. The only time a variable at namespace scope
is "static" (more correctly, has internal linkage) by default is
if it is const---the one time it is probably safe for it to be
global.
 
J

James Kanze

Really, I can remove the "static" definition and my global
variable will still "exist" for the duration of my program??

If the variable is defined at namespace scope. What other
lifetime could it conceivably have?
BTW, I know it's usually a bad idea to use global variables,
but my applications always seem to require a collection of
"state" variables that need to exist for the entire duration
of my GUI program.

The state of what? There are a few things that should exist for
the entire duration of a program, independently of what the
program does otherwise, but they aren't very frequent. (An
output stream for logging comes to mind, and in some cases,
configuration data, but that's about it.)
In your opinion, what's a good technique for managing a
collection of state variables that might need to be accessed
at any time by another C++ file module?? I usually just
create a small set of unique global variable names...if no
other variables share the same names I don't see what can go
wrong??

If it's a collection, then the first thing to do is to put it
into a class or some other single object. Then, depending on
what it's used for, associate an instance of this object with
whatever is appropriate.
 
A

Alf P. Steinbach

* James Kanze:
Except that it doesn't. Variables defined at namespace scope
(like gValue, above) are global by default; his gValue isn't
global because he's explicitly declared it not to be, by using
the keyword static. The only time a variable at namespace scope
is "static" (more correctly, has internal linkage) by default is
if it is const---the one time it is probably safe for it to be
global.

No, ..., and yes.

Re the "no", consider the need to use 'extern' in referencing declarations. And
consider C. Globals are, relatively speaking, technically easy in C.

Consider also the intricacies of global reference type thingies, not to mention,
how const is an array of const? Well I'm sure the standard clarifies this on a
case by case basis; I just don't care to remember rules that I never use. But to
my mind special case rules are not simple.

Re the "yes", well, yes.


Cheers,

- Alf
 
S

SG

James Kanze said:
[...] The only time a variable at namespace scope
is "static" (more correctly, has internal linkage) by default is
if it is const---the one time it is probably safe for it to be
global.

Isn't internal linkage the default linkage for everything you put in
unnamed namespaces as well? At least this is how I read §7.3.1.1/2:

"The use of the static keyword is deprecated when declaring
objects in a namespace scope (see annex D); the unnamed-
namespace provides a superior alternative."

Cheers,
SG
 
A

Alf P. Steinbach

* SG:
James Kanze said:
[...] The only time a variable at namespace scope
is "static" (more correctly, has internal linkage) by default is
if it is const---the one time it is probably safe for it to be
global.

Isn't internal linkage the default linkage for everything you put in
unnamed namespaces as well? At least this is how I read §7.3.1.1/2:

"The use of the static keyword is deprecated when declaring
objects in a namespace scope (see annex D); the unnamed-
namespace provides a superior alternative."

No. The whole point was to have extern linkage for e.g. using functions as
template arguments[1]. You just have a sort of like invisible internal namespace
name like an UUID xxx, as if followed by (after closing of the anon namespace)

using namespace xxx;

Cheers,

- Alf
 
J

jamm

Alf P. Steinbach wrote:
the C++ "static initialization
fiasco" e.g. in the FAQ (a very popular GUI framework suffers from this,
constraining its use severely).

Just wondering, which GUI framework are you referring to?
 
A

Alf P. Steinbach

* jamm:
Alf P. Steinbach wrote:
the C++ "static initialization

Just wondering, which GUI framework are you referring to?

wxWidgets for Windows. It's not a problem with "normal" use but I tried to use
it as underlying implementation of some more general functionality. The code is
peppered with macros that generate rather unsafe static initializations (it blew
up for my use, I started fixing things, but finally gave up, it was too much).

Hm, interesting. I wasn't sure about which GUI library so I had to search among
old projects. And when I finally found that one it had another interesting file:


<code>
struct Foo {};
struct Naughty {};

struct X: Naughty, Foo
{
#ifdef CX
X(): Naughty(), Foo() {}
#else
X() {}
#endif
};

int main()
{
X* p = new X;
delete p; // !!! defined(CX) blows up with MSVC 7.1 debug build.
}
</code>



Cheers,

- Alf
 
J

jamm

Alf said:
wxWidgets for Windows. It's not a problem with "normal" use but I tried to
use it as underlying implementation of some more general functionality.
The code is peppered with macros that generate rather unsafe static
initializations (it blew up for my use, I started fixing things, but
finally gave up, it was too much).

ahhhh I like wxWidgets.. i'll have to look into that.
 

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

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,175
Latest member
Vinay Kumar_ Nevatia
Top