By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
425,884 Members | 949 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 425,884 IT Pros & Developers. It's quick & easy.

To use global variables or no????

P: n/a
Sorry to ask another global variable question, but from reading other
posts I'm still not sure whether to use them or not.

I have a program with a set function that calls 4 other functions in
order - let's say function A, B, C, D.

It always calls function A first which is a function that returns a
system path. Now all other functions require that variable as well
(function A returns a char pointer)

So my question is - should I declare a global variable, set it's value
using function A and then use that variable in the other functions as
well.

Or is there a preferred method to achieve what I need? Hope I have made
myself clear!!

Thanks.

Jun 5 '06 #1
Share this Question
Share on Google+
37 Replies


P: n/a

eoindeb wrote:
Sorry to ask another global variable question, but from reading other
posts I'm still not sure whether to use them or not.

I have a program with a set function that calls 4 other functions in
order - let's say function A, B, C, D.

It always calls function A first which is a function that returns a
system path. Now all other functions require that variable as well
(function A returns a char pointer)

So my question is - should I declare a global variable, set it's value
using function A and then use that variable in the other functions as
well.

Or is there a preferred method to achieve what I need? Hope I have made
myself clear!!


If I understand correctly, you have one function, say F, that calls
functions A, B, C, and D in order. Function A provides input value for
the other three. I don't see why you should worry about global (file
scope) variables. Just declare a local variable in function F, and use
it to collect return value of A, and pass it to B, C, and D. Such a
variable is not global, although it is used in more functions.

Still, using variables external to the function may not be a good idea,
as looking at the function call it is not immediatelly obvious what are
the inputs, and outputs. You don't have a clean interface, you
introduce (and use) side effects.

As always, global variables do have their uses, but that has to be
judged on a case by case basis. I don't think you provide enough
information about yours to make a good guess.

Jun 5 '06 #2

P: n/a

"eoindeb" <Eo*****@gmail.com> wrote in message
news:11*********************@u72g2000cwu.googlegro ups.com...
Sorry to ask another global variable question, but from reading other
posts I'm still not sure whether to use them or not.

I have a program with a set function that calls 4 other functions in
order - let's say function A, B, C, D.

It always calls function A first which is a function that returns a
system path. Now all other functions require that variable as well
(function A returns a char pointer)

So my question is - should I declare a global variable, set it's value
using function A and then use that variable in the other functions as
well.

Or is there a preferred method to achieve what I need? Hope I have made
myself clear!!

Thanks.


One problem with global variables is that it is difficult to see where
those variables get changed. For example:

char *str;
int n = 1;

void func1() {
str = (n==1)? "hello" : "bye";
fun2();
fun3();
fun4();
fun5();
/* what are the values of n and str here ? */
The answer to the above question is: i have to examine
the code in fun2, fun3, fun4, and fun5, because I don't know
who might modify the global variables.

If you have a lot of variables that are common to several
of the functions, you can pass them all throught the call,
or you can set up a struct that contains all of the shared
variables, and just pass that struct around.

/* define struct MyStruct */
....

Then:
void func1() {
struct MyStruct s;
/* Fill in initial values */
...
fun2();
fun3(&s);
fun4();
fun5(&s);

Now I know that I only have to examine fun3 and fun5
to find possible changes to the variables.

--
Fred L. Kleinschmidt
Boeing Associate Technical Fellow
Technical Architect, Software Reuse Project

Jun 5 '06 #3

P: n/a
eoindeb said:
Sorry to ask another global variable question, but from reading other
posts I'm still not sure whether to use them or not.
First Rule of Global Variables: Don't use them.

Second Rule of Global Variables (for experts only): Don't use them *yet*.
Or is there a preferred method to achieve what I need? Hope I have made
myself clear!!


Parameters.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Jun 5 '06 #4

P: n/a

eoindeb wrote:
Sorry to ask another global variable question, but from reading other
posts I'm still not sure whether to use them or not.

I have a program with a set function that calls 4 other functions in
order - let's say function A, B, C, D.

It always calls function A first which is a function that returns a
system path. Now all other functions require that variable as well
(function A returns a char pointer)

So my question is - should I declare a global variable, set it's value
using function A and then use that variable in the other functions as
well.

Or is there a preferred method to achieve what I need? Hope I have made
myself clear!!


Pass the result of A to B, C, and D as a parameter:

char *path = A();
B(path);
C(path);
D(path);

There are several reasons why you don't want to use a global. First of
all, you won't be able to reuse B, C, or D in another module where that
global isn't defined. Secondly, your code won' t be thread-safe; If
one thread can call A and change the value of the global while another
thread is executing B, C, and D, you'll run into problems. Globals
introduce maintenance headaches; there are few things worse than
finding a bug that's due to two different pieces of code using the same
global for different reasons.

Generally speaking, you want to write your functions so that all the
information they need to do their job is provided in the parameter
list. There are times where you need to preserve state between
function calls (such as the position of a stack pointer in a stack
module), but even that can be written in such a way that the state
information is passed as a parameter, instead of stored in a global.

If you're working in an environment where stack space or register space
is at a premium and the overhead of passing a parameter is causing real
problems, then using a global is justified, but that's a fairly
specialized domain. In those cases, you'll *know* whether using a
global is the right thing to do or not.

Jun 5 '06 #5

P: n/a
On 2006-06-05, Richard Heathfield <in*****@invalid.invalid> wrote:
eoindeb said:
Sorry to ask another global variable question, but from reading other
posts I'm still not sure whether to use them or not.


First Rule of Global Variables: Don't use them.

Second Rule of Global Variables (for experts only): Don't use them *yet*.
Or is there a preferred method to achieve what I need? Hope I have made
myself clear!!


Parameters.

Regarding my earlier posts that seemed to concone global variables:

I wondered why the functions that changed my globals never confused
me; it turned out that I had been habitually passing variables by
parameter, even those that were global.

In conclusion, I moved all my globals to local scope and the code
continued to compile just fine. Lesson learned. There is virtually
never a need for globals.

--
Andrew Poelstra < http://www.wpsoftware.net/blog >
To email me, use "apoelstra" at the above address.
If we would just let the poachers into the zoo, we'd
have less squashed people and more fancy pianos!
Jun 5 '06 #6

P: n/a
"Andrew Poelstra" <ap*******@localhost.localdomain> wrote in message
news:slrne892fb.dbo.ap*******@localhost.localdomai n...
On 2006-06-05, Richard Heathfield <in*****@invalid.invalid> wrote:
eoindeb said:
Sorry to ask another global variable question, but from reading other
posts I'm still not sure whether to use them or not.


First Rule of Global Variables: Don't use them.

Second Rule of Global Variables (for experts only): Don't use them *yet*.
Or is there a preferred method to achieve what I need? Hope I have made
myself clear!!


Parameters.

Regarding my earlier posts that seemed to concone global variables:

I wondered why the functions that changed my globals never confused
me; it turned out that I had been habitually passing variables by
parameter, even those that were global.

In conclusion, I moved all my globals to local scope and the code
continued to compile just fine. Lesson learned. There is virtually
never a need for globals.


stdin
stdout
stderr
are globals.
Jun 5 '06 #7

P: n/a
On 2006-06-05, Dann Corbit <dc*****@connx.com> wrote:
"Andrew Poelstra" <ap*******@localhost.localdomain> wrote in message
news:slrne892fb.dbo.ap*******@localhost.localdomai n...
On 2006-06-05, Richard Heathfield <in*****@invalid.invalid> wrote:
eoindeb said:

Sorry to ask another global variable question, but from reading other
posts I'm still not sure whether to use them or not.

First Rule of Global Variables: Don't use them.

Second Rule of Global Variables (for experts only): Don't use them *yet*.

Or is there a preferred method to achieve what I need? Hope I have made
myself clear!!

Parameters.

Regarding my earlier posts that seemed to concone global variables:

I wondered why the functions that changed my globals never confused
me; it turned out that I had been habitually passing variables by
parameter, even those that were global.

In conclusion, I moved all my globals to local scope and the code
continued to compile just fine. Lesson learned. There is virtually
never a need for globals.


stdin
stdout
stderr
are globals.


Not sure why I have to say this, but I meant /user-defined/ globals.

Also, those aren't necessarily globals. They could be macros or some
other esoteric creature. (Unless the Standard says otherwise. Anyone?)

--
Andrew Poelstra < http://www.wpsoftware.net/blog >
To email me, use "apoelstra" at the above address.
If we would just let the poachers into the zoo, we'd
have less squashed people and more fancy pianos!
Jun 5 '06 #8

P: n/a
Andrew Poelstra said:
Dann Corbit wrote:
Andrew Poelstra wrote:

In conclusion, I moved all my globals to local scope and the code
continued to compile just fine. Lesson learned. There is virtually
never a need for globals.
stdin
stdout
stderr
are globals.


Not sure why I have to say this, but I meant /user-defined/ globals.


It's always best to say what you mean. This is almost certainly Dann's
point. Obviously you're quite new to the group and I don't know very much
about you (e.g. I don't know how old you are, and there's no reason why I
should), but if you're reasonably young it is probably true that Dann has
been writing C programs since before you were born. He knows his stuff.
Listen to Dann. Listen to Dann. He is, so to speak, one of the droids
you're looking for.

Incidentally, the term "global" is very woolly. It's best to refer to the
scope and linkage of objects rather than relying on everyone guessing that
you mean what they mean by "global".
Also, those aren't necessarily globals. They could be macros or some
other esoteric creature. (Unless the Standard says otherwise. Anyone?)


They are expressions of type "pointer to FILE". If they didn't have file
scope and external linkage, they'd be effectively unusable. It is therefore
not unreasonable to call them "globals", since they're about as global as
anything in C gets.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Jun 5 '06 #9

P: n/a
On 2006-06-05, Andrew Poelstra <ap*******@localhost.localdomain> wrote:
In conclusion, I moved all my globals to local scope and the code
continued to compile just fine. Lesson learned. There is virtually
never a need for globals.


You're not an expert yet ;-)

File-scope globals, aka statics, are extremely useful. Think for
instance of a variable with a verbosity level, you don't want to pass
that level everywhere you may want to print a debugging message. Or a
memory manager. In practice, any module which has state but for which
it would become quickly inconvenient to pass struct pointers around
all the time.

Program-level globals tend to be more useful in C++ than C, for
everything that is used a lot and happens to be a singleton. In C++ a
global object is nice, and you hide the functions as class methods.
In C OTOH you make the functions global and hide the state in statics.
I can't imagine cases where a full-on global seems the right method in
C, except for the cases where your module is too big to fit in one
source file.

OG.

Jun 5 '06 #10

P: n/a
On 2006-06-05, Richard Heathfield <in*****@invalid.invalid> wrote:
Andrew Poelstra said:
Dann Corbit wrote:
Andrew Poelstra wrote:

In conclusion, I moved all my globals to local scope and the code
continued to compile just fine. Lesson learned. There is virtually
never a need for globals.

stdin
stdout
stderr
are globals.

Not sure why I have to say this, but I meant /user-defined/ globals.


It's always best to say what you mean. This is almost certainly Dann's
point. Obviously you're quite new to the group and I don't know very much
about you (e.g. I don't know how old you are, and there's no reason why I
should), but if you're reasonably young it is probably true that Dann has
been writing C programs since before you were born. He knows his stuff.
Listen to Dann. Listen to Dann. He is, so to speak, one of the droids
you're looking for.


Thanks; it's always nice to find new teachers. You're probably right about
him coding since before I was born. Few regulars here started programming
after '91. ;-)
Incidentally, the term "global" is very woolly. It's best to refer to the
scope and linkage of objects rather than relying on everyone guessing that
you mean what they mean by "global".


I generally mean file scope, but I can see why others would have different
meanings.
Also, those aren't necessarily globals. They could be macros or some
other esoteric creature. (Unless the Standard says otherwise. Anyone?)


They are expressions of type "pointer to FILE". If they didn't have file
scope and external linkage, they'd be effectively unusable. It is therefore
not unreasonable to call them "globals", since they're about as global as
anything in C gets.


True, but FILE could be a macro. (That was my line of thinking, anyway). I
just realized that you can't have a pointer to something unnatural, so I
was wrong.

--
Andrew Poelstra < http://www.wpsoftware.net/blog >
To email me, use "apoelstra" at the above address.
If we would just let the poachers into the zoo, we'd
have less squashed people and more fancy pianos!
Jun 5 '06 #11

P: n/a
On Mon, 5 Jun 2006 13:39:46 -0700, "Dann Corbit" <dc*****@connx.com>
wrote in comp.lang.c:
"Andrew Poelstra" <ap*******@localhost.localdomain> wrote in message
news:slrne892fb.dbo.ap*******@localhost.localdomai n...
On 2006-06-05, Richard Heathfield <in*****@invalid.invalid> wrote:
eoindeb said:

Sorry to ask another global variable question, but from reading other
posts I'm still not sure whether to use them or not.

First Rule of Global Variables: Don't use them.

Second Rule of Global Variables (for experts only): Don't use them *yet*.

Or is there a preferred method to achieve what I need? Hope I have made
myself clear!!

Parameters.

Regarding my earlier posts that seemed to concone global variables:

I wondered why the functions that changed my globals never confused
me; it turned out that I had been habitually passing variables by
parameter, even those that were global.

In conclusion, I moved all my globals to local scope and the code
continued to compile just fine. Lesson learned. There is virtually
never a need for globals.


stdin
stdout
stderr
are globals.


No, they're not, they're macros.

Long time, Dann. How the heck are you?

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Jun 6 '06 #12

P: n/a
"Jack Klein" <ja*******@spamcop.net> wrote in message
news:92********************************@4ax.com...
On Mon, 5 Jun 2006 13:39:46 -0700, "Dann Corbit" <dc*****@connx.com>
wrote in comp.lang.c:
"Andrew Poelstra" <ap*******@localhost.localdomain> wrote in message
news:slrne892fb.dbo.ap*******@localhost.localdomai n...
> On 2006-06-05, Richard Heathfield <in*****@invalid.invalid> wrote:
>> eoindeb said:
>>
>>> Sorry to ask another global variable question, but from reading other
>>> posts I'm still not sure whether to use them or not.
>>
>> First Rule of Global Variables: Don't use them.
>>
>> Second Rule of Global Variables (for experts only): Don't use them
>> *yet*.
>>
>>> Or is there a preferred method to achieve what I need? Hope I have
>>> made
>>> myself clear!!
>>
>> Parameters.
>>
> Regarding my earlier posts that seemed to concone global variables:
>
> I wondered why the functions that changed my globals never confused
> me; it turned out that I had been habitually passing variables by
> parameter, even those that were global.
>
> In conclusion, I moved all my globals to local scope and the code
> continued to compile just fine. Lesson learned. There is virtually
> never a need for globals.
stdin
stdout
stderr
are globals.


No, they're not, they're macros.


True, but they must resolve to type pointer to file:

Page 262:
stderr
stdin
stdout
which are expressions of type ''pointer to FILE'' that point to the FILE
objects
associated, respectively, with the standard error, input, and output
streams.
Long time, Dann. How the heck are you?
Peachy-creamy with a cherry on top, as usual.
--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html

Jun 6 '06 #13

P: n/a
On Mon, 05 Jun 2006 16:02:21 +0000, Richard Heathfield
<in*****@invalid.invalid> wrote:
eoindeb said:
Sorry to ask another global variable question, but from reading other
posts I'm still not sure whether to use them or not.


First Rule of Global Variables: Don't use them.


The C Standard really makes no mention of "Global Variables". I hope
that what you are referring to as "Global Variables" are variables
visible to two or more translation units, e.g.:

// foo.h
extern int iBar;

and not file scope variables, e.g.:

// foo.c
static int iBar;

--
jay

Jun 6 '06 #14

P: n/a
"jaysome" <ja*****@spamcop.net> wrote in message
news:sq********************************@4ax.com...
On Mon, 05 Jun 2006 16:02:21 +0000, Richard Heathfield
<in*****@invalid.invalid> wrote:
eoindeb said:
Sorry to ask another global variable question, but from reading other
posts I'm still not sure whether to use them or not.


First Rule of Global Variables: Don't use them.


The C Standard really makes no mention of "Global Variables". I hope
that what you are referring to as "Global Variables" are variables
visible to two or more translation units, e.g.:

// foo.h
extern int iBar;

and not file scope variables, e.g.:

// foo.c
static int iBar;


If variable iBar could be an auto, then this is a mistake (as you probably
know, but I am emphasizing it).

The general rule of thumb is that scope should be minimized.
Make a variable auto, if it does not have to be static.
Make a variable static, if it does not have to be extern.
Make a variable extern if there is no other way (e.g. a file handle that
everyone will have to be able to use directly like stdin.)

Besides the greatly simplified debugging, you will be very happy when it is
time to make a threaded version. Yes, I know. C has no concept of threads.
But you will probably have to write a threaded version eventually,
nevertheless. If you used nothing but auto variables (and if any static
variables are const), then the threaded version is the same as the
non-threaded version.
Jun 6 '06 #15

P: n/a
Jack Klein <ja*******@spamcop.net> writes:
On Mon, 5 Jun 2006 13:39:46 -0700, "Dann Corbit" <dc*****@connx.com>
wrote in comp.lang.c:

[...]
stdin
stdout
stderr
are globals.


No, they're not, they're macros.


So it would seem, but I wonder if that was the intent.

C99 7.19.1 says:

The header <stdio.h> declares three types, several macros, and
many functions for performing input and output.

...

The macros are NULL (described in 7.17);

...

stderr
stdin
stdout

which are expressions of type "pointer to FILE" that point to the
FILE objects associated, respectively, with the standard error,
input, and output streams.

For all the other macros, the standard says "which expands to ...";
for stderr, stdin, and stdout, it says that they *are* expressions.
And I can't think of any good reason why an implementation couldn't
declare them as global objects rather than as macros (except of
course, that a program can tell the difference using #ifdef).

Off to comp.std.c.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Jun 6 '06 #16

P: n/a
jaysome said:
On Mon, 05 Jun 2006 16:02:21 +0000, Richard Heathfield
<in*****@invalid.invalid> wrote:
eoindeb said:
Sorry to ask another global variable question, but from reading other
posts I'm still not sure whether to use them or not.
First Rule of Global Variables: Don't use them.


The C Standard really makes no mention of "Global Variables".


As I keep telling people, except that I thought nobody ever listened.
Perhaps someone finally did.
I hope
that what you are referring to as "Global Variables" are variables
visible to two or more translation units,
No, I'm talking about non-const objects that are not auto objects.
e.g.:

// foo.h
extern int iBar;

and not file scope variables, e.g.:

// foo.c
static int iBar;


Now try to come up with a plausible reason why a good programmer would need
this static int.

I can think of two reasons off-hand for using non-auto non-const objects,
one of which I don't like but am prepared to accept, and the other of which
I don't like but don't have any choice about accepting.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Jun 6 '06 #17

P: n/a
Richard Heathfield <in*****@invalid.invalid> writes:
I can think of two reasons off-hand for using non-auto non-const objects,
one of which I don't like but am prepared to accept, and the other of which
I don't like but don't have any choice about accepting.


I might be misunderstanding you, but don't some types of function need
to keep "static" state information? E.g. functions like malloc?

--

John Devereux
Jun 6 '06 #18

P: n/a
On Tue, 06 Jun 2006 19:01:27 +0100, John Devereux
<jd******@THISdevereux.me.uk> wrote:
Richard Heathfield <in*****@invalid.invalid> writes:
I can think of two reasons off-hand for using non-auto non-const objects,
one of which I don't like but am prepared to accept, and the other of which
I don't like but don't have any choice about accepting.


I might be misunderstanding you, but don't some types of function need
to keep "static" state information? E.g. functions like malloc?


I may also be misunderstanding, but I often find static objects useful
when writing access functions for opaque types.

--
Al Balmer
Sun City, AZ
Jun 6 '06 #19

P: n/a
"Al Balmer" <al******@att.net> wrote in message
news:6a********************************@4ax.com...
On Tue, 06 Jun 2006 19:01:27 +0100, John Devereux
<jd******@THISdevereux.me.uk> wrote:
Richard Heathfield <in*****@invalid.invalid> writes:
I can think of two reasons off-hand for using non-auto non-const
objects,
one of which I don't like but am prepared to accept, and the other of
which
I don't like but don't have any choice about accepting.
I might be misunderstanding you, but don't some types of function need
to keep "static" state information? E.g. functions like malloc?


I may also be misunderstanding, but I often find static objects useful
when writing access functions for opaque types.


Static data objects are useful when there is no better way to achieve the
same desired result (typically, persistent state information that needs
exactly one copy for the duration of program execution). On the other hand,
they (static data objects) often cause a lot more problems than they solve.
A typical example is strtok(). Because strtok() maintains static
information, calling strtok() from two different locations in your program
can lead to subtle bugs. The strtok_r() design is a much better design for
that reason.
--
Al Balmer
Sun City, AZ

Jun 6 '06 #20

P: n/a
John Devereux wrote:
Richard Heathfield <in*****@invalid.invalid> writes:
I can think of two reasons off-hand for using non-auto non-const
objects, one of which I don't like but am prepared to accept, and
the other of which I don't like but don't have any choice about
accepting.


I might be misunderstanding you, but don't some types of function
need to keep "static" state information? E.g. functions like malloc?


Not malloc. strtok() yes.

--
"Our enemies are innovative and resourceful, and so are we.
They never stop thinking about new ways to harm our country
and our people, and neither do we." -- G. W. Bush.
"The people can always be brought to the bidding of the
leaders. All you have to do is tell them they are being
attacked and denounce the pacifists for lack of patriotism
and exposing the country to danger. It works the same way
in any country." --Hermann Goering.
Jun 6 '06 #21

P: n/a


CBFalconer wrote On 06/06/06 14:54,:
John Devereux wrote:
Richard Heathfield <in*****@invalid.invalid> writes:

I can think of two reasons off-hand for using non-auto non-const
objects, one of which I don't like but am prepared to accept, and
the other of which I don't like but don't have any choice about
accepting.


I might be misunderstanding you, but don't some types of function
need to keep "static" state information? E.g. functions like malloc?

Not malloc. strtok() yes.


How can malloc() recycle memory released by free()
if the two functions don't share at least one static
variable?

Similar concerns apply elsewhere in the library:
exit() must call (and hence find) all the functions
registered with atexit(), and must close (and hence
find) all the streams opened with fopen() and not yet
closed with fclose(). fflush(NULL) must find all the
open streams whose last operation was an output. The
<locale.h> mechanisms can change the behavior of the
<ctype.h> functions. And so on, and so on ... How
are any of these interactions to be handled without
static data?

Of course, non-C languages might provide means
other than static variables for sharing persistent data
across "function" invocations. And it's well known that
the C library is not required to be written in C -- but
that's a long way from requiring that it *not* be written
in C!

--
Er*********@sun.com

Jun 6 '06 #22

P: n/a
"Eric Sosman" <Er*********@sun.com> wrote in message
news:1149626369.617117@news1nwk...


CBFalconer wrote On 06/06/06 14:54,:
John Devereux wrote:
Richard Heathfield <in*****@invalid.invalid> writes:
I can think of two reasons off-hand for using non-auto non-const
objects, one of which I don't like but am prepared to accept, and
the other of which I don't like but don't have any choice about
accepting.

I might be misunderstanding you, but don't some types of function
need to keep "static" state information? E.g. functions like malloc?

Not malloc. strtok() yes.


How can malloc() recycle memory released by free()
if the two functions don't share at least one static
variable?

Similar concerns apply elsewhere in the library:
exit() must call (and hence find) all the functions
registered with atexit(), and must close (and hence
find) all the streams opened with fopen() and not yet
closed with fclose(). fflush(NULL) must find all the
open streams whose last operation was an output. The
<locale.h> mechanisms can change the behavior of the
<ctype.h> functions. And so on, and so on ... How
are any of these interactions to be handled without
static data?


Why not use allocated memory? (Sounds a bit recursive with malloc(), but we
can use an OS-level allocator.).

E.g. When a file is opened, add the file handle along with any other needed
data to a skiplist.
When the file is closed or the program exits, remove the object from the
skiplist after performing all necessary cleanup operations.

Similarly for all of the others. I would submit that extern and static are
never really needed. We just use them because we're lazy.

For a single instance variable, I could make it an auto at main() level and
pass it as a parameter. But I may feel lazy and make it static or even
extern so I don't have to add the argument to all of the functions that need
it.

I guess that global variables are not needed ever. But I probably just fail
to use proper vision in thinking the problem through.
Of course, non-C languages might provide means
other than static variables for sharing persistent data
across "function" invocations. And it's well known that
the C library is not required to be written in C -- but
that's a long way from requiring that it *not* be written
in C!

--
Er*********@sun.com

Jun 6 '06 #23

P: n/a


Dann Corbit wrote On 06/06/06 17:02,:
"Eric Sosman" <Er*********@sun.com> wrote in message
news:1149626369.617117@news1nwk...

CBFalconer wrote On 06/06/06 14:54,:
John Devereux wrote:
Richard Heathfield <in*****@invalid.invalid> writes:

>I can think of two reasons off-hand for using non-auto non-const
>objects, one of which I don't like but am prepared to accept, and
>the other of which I don't like but don't have any choice about
>accepting.

I might be misunderstanding you, but don't some types of function
need to keep "static" state information? E.g. functions like malloc?
Not malloc. strtok() yes.


How can malloc() recycle memory released by free()
if the two functions don't share at least one static
variable?

Similar concerns apply elsewhere in the library:
exit() must call (and hence find) all the functions
registered with atexit(), and must close (and hence
find) all the streams opened with fopen() and not yet
closed with fclose(). fflush(NULL) must find all the
open streams whose last operation was an output. The
<locale.h> mechanisms can change the behavior of the
<ctype.h> functions. And so on, and so on ... How
are any of these interactions to be handled without
static data?

Why not use allocated memory? (Sounds a bit recursive with malloc(), but we
can use an OS-level allocator.).

E.g. When a file is opened, add the file handle along with any other needed
data to a skiplist.
When the file is closed or the program exits, remove the object from the
skiplist after performing all necessary cleanup operations.

Similarly for all of the others. I would submit that extern and static are
never really needed. We just use them because we're lazy.


extern, no. But I don't see a way to do without static.
The skip list you mention, for instance: How do all of the
functions fopen(), fclose(), fflush(), and exit() manage to
find the list's first node? Even if they call __find_list(void)
to locate it, where does __find_list() store the pointer if
not in a static variable of its own?

Even if we make all things that are usually static reside
in a dynamically-allocated data structure whose address is
obtained from some magical system call, how would this be an
improvement over using global variables? That is, what is
the fundamental difference between

extern int global;
void f(void) {
global = 42;
}

and

void f(void) {
ProgramContext *ctx = __get_program_context_pointer();
ctx->global = 42;
}

? Wouldn't this just substitute an explicit pointer for the
implicit "pointer" expressed by the values in MMU registers?

Maybe all this confusion stems from different understandings
of the loose term "global." I sure hope so: it makes me nervous
when Falconer and Corbit both disagree with me ... I'm reminded
(uncomfortably) of Pauli's hubris in remarking "What Professor
Einstein has just said is not so stupid."

--
Er*********@sun.com

Jun 6 '06 #24

P: n/a
"Eric Sosman" <Er*********@sun.com> wrote in message
news:1149629458.144029@news1nwk...


Dann Corbit wrote On 06/06/06 17:02,:
"Eric Sosman" <Er*********@sun.com> wrote in message
news:1149626369.617117@news1nwk...

CBFalconer wrote On 06/06/06 14:54,:

John Devereux wrote:
>Richard Heathfield <in*****@invalid.invalid> writes:
>
>
>
>>I can think of two reasons off-hand for using non-auto non-const
>>objects, one of which I don't like but am prepared to accept, and
>>the other of which I don't like but don't have any choice about
>>accepting.
>
>I might be misunderstanding you, but don't some types of function
>need to keep "static" state information? E.g. functions like malloc?
Not malloc. strtok() yes.

How can malloc() recycle memory released by free()
if the two functions don't share at least one static
variable?

Similar concerns apply elsewhere in the library:
exit() must call (and hence find) all the functions
registered with atexit(), and must close (and hence
find) all the streams opened with fopen() and not yet
closed with fclose(). fflush(NULL) must find all the
open streams whose last operation was an output. The
<locale.h> mechanisms can change the behavior of the
<ctype.h> functions. And so on, and so on ... How
are any of these interactions to be handled without
static data?

Why not use allocated memory? (Sounds a bit recursive with malloc(), but
we
can use an OS-level allocator.).

E.g. When a file is opened, add the file handle along with any other
needed
data to a skiplist.
When the file is closed or the program exits, remove the object from the
skiplist after performing all necessary cleanup operations.

Similarly for all of the others. I would submit that extern and static
are
never really needed. We just use them because we're lazy.


extern, no. But I don't see a way to do without static.
The skip list you mention, for instance: How do all of the
functions fopen(), fclose(), fflush(), and exit() manage to
find the list's first node? Even if they call __find_list(void)
to locate it, where does __find_list() store the pointer if
not in a static variable of its own?

Even if we make all things that are usually static reside
in a dynamically-allocated data structure whose address is
obtained from some magical system call, how would this be an
improvement over using global variables? That is, what is
the fundamental difference between

extern int global;
void f(void) {
global = 42;
}

and

void f(void) {
ProgramContext *ctx = __get_program_context_pointer();
ctx->global = 42;
}

? Wouldn't this just substitute an explicit pointer for the
implicit "pointer" expressed by the values in MMU registers?

Maybe all this confusion stems from different understandings
of the loose term "global." I sure hope so: it makes me nervous
when Falconer and Corbit both disagree with me ... I'm reminded
(uncomfortably) of Pauli's hubris in remarking "What Professor
Einstein has just said is not so stupid."


I'm not necessarily disagreeing. Although dynamic allocation could replace
the use of static instance variables, it is not necessarily a better
solution. There is a difference between "You don't have to do it this way"
and "It's not as good to do it this way."

Almost all of the programming that I do is mutlithreaded and multiprocess
and so I tend to think of anything global or writable static as evil.
However, I imagine that sometimes they may be a necessary evil. There are
ways to avoid using static and extern but the solutions may be worse than
the problem they are trying to cure.

For instance, my assertion to use dynamic allocation introduces a new
problem:
How to handle resource allocation failure.
That problem does not exist with a pre-defined instance variable which we
know exists if the compile succeeds.

I almost never use global variables. But my abhorrence is from all the
effort I expend in avoiding or removing them, no doubt. --
Er*********@sun.com

Jun 6 '06 #25

P: n/a
Eric Sosman wrote:
CBFalconer wrote On 06/06/06 14:54,:
John Devereux wrote:
Richard Heathfield <in*****@invalid.invalid> writes:

I can think of two reasons off-hand for using non-auto non-const
objects, one of which I don't like but am prepared to accept, and
the other of which I don't like but don't have any choice about
accepting.

I might be misunderstanding you, but don't some types of function
need to keep "static" state information? E.g. functions like malloc?


Not malloc. strtok() yes.


How can malloc() recycle memory released by free()
if the two functions don't share at least one static
variable?


True enough. I was guilty of sloppy thinking. However, in
justification, I think of the malloc system as a separate entity,
mediating between the fixed resources (as supplied via sbrk) and
the running program(s). As long as suitable synchronizaton steps
are taken to avoid fouling of variables, the system can be
re-entrant and thread safe.

However, for one thread (which is all we officially have in C)
there is no problem mixing calls to the malloc family. strtok is
another matter entirely.

--
"Our enemies are innovative and resourceful, and so are we.
They never stop thinking about new ways to harm our country
and our people, and neither do we." -- G. W. Bush.
"The people can always be brought to the bidding of the
leaders. All you have to do is tell them they are being
attacked and denounce the pacifists for lack of patriotism
and exposing the country to danger. It works the same way
in any country." --Hermann Goering.

Jun 6 '06 #26

P: n/a
John Devereux said:
Richard Heathfield <in*****@invalid.invalid> writes:
I can think of two reasons off-hand for using non-auto non-const objects,
one of which I don't like but am prepared to accept, and the other of
which I don't like but don't have any choice about accepting.


I might be misunderstanding you, but don't some types of function need
to keep "static" state information? E.g. functions like malloc?


My apologies, John, for not making myself clear enough. I wasn't thinking
about implementing the standard library, but about more general programming
tasks. It would be impossible, I think, to write strtok in C without using
a static duration object. And yes, the mm subsystem needs to keep some
state too. (Actually, strtok /wouldn't/ need to keep state if they'd
thought about it a bit more; it appears to have been conceived in the days
when "get it done and never mind how as long as it's quick" was a view more
widely held than it is today.)

The two uses I had in mind are:

(a) you have a whole bunch of configuration information, which is needed by
just about every function in your shiny new library (for example, the
current default size for dynamic buffers, that sort of thing), and you
don't wish to impose upon your users the burden of passing a
pointer-to-config-info to absolutely every function in the library. That's
the use I don't like, but I can live with.
(b) signal handling. Just about the only thing you can do portably in a
signal handler is change the value of a sig_atomic_t object. And there is
no mechanism in the signal handler prototype to handle sig_atomic_t
objects! AAARGH! So you don't have much choice but to bang in a static at
file scope.
--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Jun 6 '06 #27

P: n/a
Richard Heathfield <in*****@invalid.invalid> writes:
John Devereux said:
Richard Heathfield <in*****@invalid.invalid> writes:
I can think of two reasons off-hand for using non-auto non-const objects,
one of which I don't like but am prepared to accept, and the other of
which I don't like but don't have any choice about accepting.
I might be misunderstanding you, but don't some types of function need
to keep "static" state information? E.g. functions like malloc?


My apologies, John, for not making myself clear enough.


That's OK. I could see you were in riddle mode :)

I wasn't thinking about implementing the standard library, but about
more general programming tasks. It would be impossible, I think, to
write strtok in C without using a static duration object. And yes,
the mm subsystem needs to keep some state too. (Actually, strtok
/wouldn't/ need to keep state if they'd thought about it a bit more;
it appears to have been conceived in the days when "get it done and
never mind how as long as it's quick" was a view more widely held
than it is today.)

The two uses I had in mind are:

(a) you have a whole bunch of configuration information, which is needed by
just about every function in your shiny new library (for example, the
current default size for dynamic buffers, that sort of thing), and you
don't wish to impose upon your users the burden of passing a
pointer-to-config-info to absolutely every function in the library. That's
the use I don't like, but I can live with.


This is what I end up using them for. I have a global structure, say
"settings". Lots of functions need to be able to access the members,
in lots of different modules. Most functions only need access to a
couple of members each. But they need to be in a single big structure
so that menu and serialisation code can get at them conveniently. I
can pass around pointers to that structure, and have the structure
declared "static" somewhere at file scope instead of "extern". But I
am not really sure I gain anything by doing that!

I keep thinking there must be a better way but have not found one
yet...

--

John Devereux
Jun 6 '06 #28

P: n/a
John Devereux <jd******@THISdevereux.me.uk> writes:
Richard Heathfield <in*****@invalid.invalid> writes:
I can think of two reasons off-hand for using non-auto non-const objects,
one of which I don't like but am prepared to accept, and the other of which
I don't like but don't have any choice about accepting.


I might be misunderstanding you, but don't some types of function need
to keep "static" state information? E.g. functions like malloc?


The malloc, calloc, realloc, and free functions almost certainly need
to keep some state information (with static storage duration) that
they share. (That's assuming they're implemented in C, which isn't
required.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Jun 7 '06 #29

P: n/a
av
On Tue, 06 Jun 2006 -0400, Eric Sosman wrote:
Dann Corbit wrote On 06/06/06 17:02,:
"Eric Sosman" wrote in message
news:1149626369.617117@news1nwk...
CBFalconer wrote On 06/06/06 14:54,:

John Devereux wrote:
>Richard Heathfield <in*****@invalid.invalid> writes:
>
>
>
>>I can think of two reasons off-hand for using non-auto non-const
>>objects, one of which I don't like but am prepared to accept, and
>>the other of which I don't like but don't have any choice about
>>accepting.
>
>I might be misunderstanding you, but don't some types of function
>need to keep "static" state information? E.g. functions like malloc?
Not malloc. strtok() yes.

How can malloc() recycle memory released by free()
if the two functions don't share at least one static
variable?

Similar concerns apply elsewhere in the library:
exit() must call (and hence find) all the functions
registered with atexit(), and must close (and hence
find) all the streams opened with fopen() and not yet
closed with fclose(). fflush(NULL) must find all the
open streams whose last operation was an output. The
<locale.h> mechanisms can change the behavior of the
<ctype.h> functions. And so on, and so on ... How
are any of these interactions to be handled without
static data?

Why not use allocated memory? (Sounds a bit recursive with malloc(), but we
can use an OS-level allocator.).

E.g. When a file is opened, add the file handle along with any other needed
data to a skiplist.
When the file is closed or the program exits, remove the object from the
skiplist after performing all necessary cleanup operations.

Similarly for all of the others. I would submit that extern and static are
never really needed. We just use them because we're lazy.


extern, no. But I don't see a way to do without static.
The skip list you mention, for instance: How do all of the
functions fopen(), fclose(), fflush(), and exit() manage to
find the list's first node? Even if they call __find_list(void)
to locate it, where does __find_list() store the pointer if
not in a static variable of its own?


in assembly there is a BSS section that reserve memory in the stack
for its variable-data definitions. (if i remember well)
don't know if i can compile to object file an assembly file that has
all names in the BSS section and compile that obj-file with the C one
file that has routines that see the names in the assembly BSS section.
Don't know if it is right...
Jun 7 '06 #30

P: n/a
>>> Why not use allocated memory? (Sounds a bit recursive with malloc(), but we
can use an OS-level allocator.).

E.g. When a file is opened, add the file handle along with any other needed
data to a skiplist.
When the file is closed or the program exits, remove the object from the
skiplist after performing all necessary cleanup operations.

Similarly for all of the others. I would submit that extern and static are
never really needed. We just use them because we're lazy.
extern, no. But I don't see a way to do without static.
The skip list you mention, for instance: How do all of the
functions fopen(), fclose(), fflush(), and exit() manage to
find the list's first node? Even if they call __find_list(void)
to locate it, where does __find_list() store the pointer if
not in a static variable of its own?


in assembly there is a BSS section that reserve memory in the stack
for its variable-data definitions. (if i remember well)


You don't. BSS reserves memory in the *NON*-stack (which is still
true for systems that have BSS but don't have a hardware stack) for
its variable-data definitions. What gets put there? uninitialized
non-auto, non-const variables. Static and extern.
don't know if i can compile to object file an assembly file that has
all names in the BSS section and compile that obj-file with the C one
file that has routines that see the names in the assembly BSS section.
Don't know if it is right...


It's possible, but the variables are exactly the types that some
people are declaring evil.

Gordon L. Burditt
Jun 7 '06 #31

P: n/a
"Dann Corbit" <dc*****@connx.com> wrote:
"Eric Sosman" <Er*********@sun.com> wrote in message
news:1149626369.617117@news1nwk...
How can malloc() recycle memory released by free()
if the two functions don't share at least one static
variable?

Similar concerns apply elsewhere in the library:
exit() must call (and hence find) all the functions
registered with atexit(), and must close (and hence
find) all the streams opened with fopen() and not yet
closed with fclose(). fflush(NULL) must find all the
open streams whose last operation was an output. The
<locale.h> mechanisms can change the behavior of the
<ctype.h> functions. And so on, and so on ... How
are any of these interactions to be handled without
static data?


Why not use allocated memory? (Sounds a bit recursive with malloc(), but we
can use an OS-level allocator.).

E.g. When a file is opened, add the file handle along with any other needed
data to a skiplist.


How does malloc() remember where its skiplist starts?

Richard
Jun 7 '06 #32

P: n/a
"Richard Bos" <rl*@hoekstra-uitgeverij.nl> wrote in message
news:44****************@news.xs4all.nl...
"Dann Corbit" <dc*****@connx.com> wrote:
"Eric Sosman" <Er*********@sun.com> wrote in message
news:1149626369.617117@news1nwk...
> How can malloc() recycle memory released by free()
> if the two functions don't share at least one static
> variable?
>
> Similar concerns apply elsewhere in the library:
> exit() must call (and hence find) all the functions
> registered with atexit(), and must close (and hence
> find) all the streams opened with fopen() and not yet
> closed with fclose(). fflush(NULL) must find all the
> open streams whose last operation was an output. The
> <locale.h> mechanisms can change the behavior of the
> <ctype.h> functions. And so on, and so on ... How
> are any of these interactions to be handled without
> static data?
Why not use allocated memory? (Sounds a bit recursive with malloc(), but
we
can use an OS-level allocator.).

E.g. When a file is opened, add the file handle along with any other
needed
data to a skiplist.


How does malloc() remember where its skiplist starts?


The malloc function puts a struct into a skiplist with an auto root node at
the scope of main (or even above it, since it is a compiler implemented
function). The struct in the skiplist stores the address, the size, and any
other relevant data. When someone calls free() the address is the key for
the skiplist. If the address is NULL, the function returns. Otherwise, the
address is searched for in the skiplist. If the address is found, the
memory is returned to the operating system.
Richard

Jun 7 '06 #33

P: n/a
>> How does malloc() remember where its skiplist starts?

The malloc function puts a struct into a skiplist with an auto root node at
the scope of main (or even above it, since it is a compiler implemented
function).
If it's written in C, malloc() (or any other function) cannot put
a auto root node at a scope other than itself. C is not Pascal.
And ANSI C doesn't allow you to require passing the address of that
node to malloc(). And if the scope is that of malloc(), the value
goes away when malloc() returns.

You've still got a variable that is accessed by several different
functions that retains its value between calls. That sounds like
a non-auto, non-const variable (often called a "global") to me.
And it has the problems of one - being accessible from all over.
The struct in the skiplist stores the address, the size, and any
other relevant data.
Fine, *if* the skiplist can be found.
When someone calls free() the address is the key for
the skiplist.
So how does free() find the root node for the skiplist?
If the address is NULL, the function returns. Otherwise, the
address is searched for in the skiplist. If the address is found, the
memory is returned to the operating system.


Gordon L. Burditt
Jun 7 '06 #34

P: n/a
"Dann Corbit" <dc*****@connx.com> wrote:
"Richard Bos" <rl*@hoekstra-uitgeverij.nl> wrote in message
news:44****************@news.xs4all.nl...
"Dann Corbit" <dc*****@connx.com> wrote:
"Eric Sosman" <Er*********@sun.com> wrote in message
news:1149626369.617117@news1nwk...
> How can malloc() recycle memory released by free()
> if the two functions don't share at least one static
> variable? Why not use allocated memory? (Sounds a bit recursive with malloc(), but
we can use an OS-level allocator.).

E.g. When a file is opened, add the file handle along with any other
needed data to a skiplist.
How does malloc() remember where its skiplist starts?


The malloc function puts a struct into a skiplist with an auto root node at
the scope of main


It can't do that, since free() must be callable from atexit()-functions.
What's more, that skiplist must have (what amounts to) a declaration in
scope for both malloc() and free().
(or even above it, since it is a compiler implemented function).


It _can_ do this, but I would argue that that is the same thing as
creating a static object - perhaps in different terms, but the same
thing functionally.

Richard
Jun 7 '06 #35

P: n/a
"Gordon Burditt" <go***********@burditt.org> wrote in message
news:12*************@corp.supernews.com...
How does malloc() remember where its skiplist starts?


The malloc function puts a struct into a skiplist with an auto root node
at
the scope of main (or even above it, since it is a compiler implemented
function).


If it's written in C, malloc() (or any other function) cannot put
a auto root node at a scope other than itself. C is not Pascal.
And ANSI C doesn't allow you to require passing the address of that
node to malloc(). And if the scope is that of malloc(), the value
goes away when malloc() returns.

You've still got a variable that is accessed by several different
functions that retains its value between calls. That sounds like
a non-auto, non-const variable (often called a "global") to me.
And it has the problems of one - being accessible from all over.
The struct in the skiplist stores the address, the size, and any
other relevant data.


Fine, *if* the skiplist can be found.
When someone calls free() the address is the key for
the skiplist.


So how does free() find the root node for the skiplist?
If the address is NULL, the function returns. Otherwise, the
address is searched for in the skiplist. If the address is found, the
memory is returned to the operating system.


Gordon L. Burditt


This is not a user-level operation. It is at the compiler vendor level. I
imagine something like this:

void magic_compiler_level_thing_over_main()
{
memory_node_t root;
allocator_initialization(root);
main(); /* malloc and free use the data structure created above */
}
Jun 7 '06 #36

P: n/a
>>>The malloc function puts a struct into a skiplist with an auto root node
at
the scope of main (or even above it, since it is a compiler implemented
function).


If it's written in C, malloc() (or any other function) cannot put
a auto root node at a scope other than itself. C is not Pascal.
And ANSI C doesn't allow you to require passing the address of that
node to malloc(). And if the scope is that of malloc(), the value
goes away when malloc() returns.

You've still got a variable that is accessed by several different
functions that retains its value between calls. That sounds like
a non-auto, non-const variable (often called a "global") to me.
And it has the problems of one - being accessible from all over.
The struct in the skiplist stores the address, the size, and any
other relevant data.


Fine, *if* the skiplist can be found.
When someone calls free() the address is the key for
the skiplist.


So how does free() find the root node for the skiplist?
If the address is NULL, the function returns. Otherwise, the
address is searched for in the skiplist. If the address is found, the
memory is returned to the operating system.


Gordon L. Burditt


This is not a user-level operation. It is at the compiler vendor level. I
imagine something like this:

void magic_compiler_level_thing_over_main()
{
memory_node_t root;
allocator_initialization(root);
main(); /* malloc and free use the data structure created above */
}


I'd expect the parameter passed to allocator_initialization to be &root,
not root, unless a memory_node_t is an array.

So where does allocator_initialization() store the root node (or
its address) so malloc() and free() can get to it? It sounds to
me liek allocator_initialization() is, among other things, sticking
a pointer value into a non-auto, non-const variable for later use
by malloc() or free(). (You could do it by having
allocator_initialization(NULL) return the address of the root node,
rather than have malloc() and free() access it directly. That still
requires allocator_initialization() to use a static.

Gordon L. Burditt
Jun 7 '06 #37

P: n/a

"eoindeb" <Eo*****@gmail.com> wrote in message
news:11*********************@u72g2000cwu.googlegro ups.com...
Sorry to ask another global variable question, but from reading other
posts I'm still not sure whether to use them or not.

I have a program with a set function that calls 4 other functions in
order - let's say function A, B, C, D.

It always calls function A first which is a function that returns a
system path. Now all other functions require that variable as well
(function A returns a char pointer)

So my question is - should I declare a global variable, set it's value
using function A and then use that variable in the other functions as
well.

Or is there a preferred method to achieve what I need? Hope I have made
myself clear!!

As a general rule, don't use global variables.
It introduces a dependency, which means that the function only works if its
parameters are correct, and the global is set up correctly. This is hard for
a human to achieve.

However there are some exceptions. For instance if a function is called
indirectly, like the comparison to qsort, and needs state information to do
its stuff, it is alot easier to just use a global rather than try to set up
some scheme whereby the pointer is attached to the sort structures.

Another one is recursive functions which take a lot of parameters. Because
the function may call itself thousands of times, often it is worth while
separating out the constant parameters that don't change during the
recursion, to avoid unnececcary stack set ups.

Don't be afraid of passing a parameter down three or four levels to where it
is used, however. Often that makes perfect sense.

--
Buy my book 12 Common Atheist Arguments (refuted)
$1.25 download or $7.20 paper, available www.lulu.com/bgy1mm
Jun 8 '06 #38

This discussion thread is closed

Replies have been disabled for this discussion.