Re: Poll: global buffers (long)

From: George Greer (greerga@circlemud.org)
Date: 07/21/01


NOTE: Remember possible Devil's Advocate arguments.  Some get quite absurd.

[This message delayed by my T1 having a meltdown...seems stable enough to
send at the moment though it's quite spotty.]

On Fri, 20 Jul 2001, Bil Simser wrote:

>First off, global anything in general programming 101 is a bad thing?
>It's sloppy and lazy coding. Even back in the old C days before there was
>a hint of C++ or OO design in C programming, the hard and fast rule (as
>told by K&R) was to not use global anything. Encapsulate all programming
>so you either declare it on the stack and it will be tossed away after
>the function goes out of scope or pass the value in by value or by
>reference (depending on what you need to do with it) and keep everything
>neat and tight like a good boy scout.

All things in moderation.  It isn't always bad. Imagine doing that with
'mini_mud' or 'no_specials'.  Must I pass 5 variable arguments through 10
functions that don't care just to get to the one that does?  Assume we
throw all those flags into a single structure to keep it from being 5
variables.  Is it better to now pass that single variable through 10
functions that never use it for the one that does?

>The one thing that does bother me about the buffer system is the fact
>that a) it's global and hence is a potential accident waiting to happen
>(see below) and b) requires extra attention to checking for global
>overruns and magic numbers and all that jazz.

The extra attention is only possible because they are global.  We can then
check to make sure all uses of that buffer have been kosher.  With stack
allocations we'd have to trap at every single function exit to see if we
overflowed.  It's not a foolproof catch since you can crash before ever
making it to the check, which an every-function method could do.

>Why is a global buffer system bad? Because it means that if I write to
>buf (or buf2, or ...) then that information stays there even when in a
>function that doesn't need it. Let's say I decide to write a new
>command. I build the prototype and just call send_to_char(buf) to the
>user. Whatever was in buf before is repeated to the user. Could be
>something useful, but certainly not what was expected.

So you place 'buf' on the stack and get whatever the function that
previously used that stack space made.  Sure, you're no longer guaranteed
to get some sort of string now but it's still possible.

>There's also the issue that you need to be aware that these buffers
>exist. That, IMO, is usually a bad thing especially for new coders. When
>you see a function that immediately calls *buf = '\0' you wonder, "buf??
>what is that!".

True, the magical argument.

>Also, as someone pointed out, it's really, really bad practice to rely on
>information to be passed around using global buffers like the locate
>object issue.

'locate object' is a completely different issue.

  /*
   * FIXME: This is broken.  The spell parser routines took the argument
   * the player gave to the spell and located an object with that keyword.
   * Since we're passed the object and not the keyword we can only guess
   * at what the player originally meant to search for. -gg
   */

>As well, what if you decide that you want to modify a function by
>inserting a call to something that by nature writes something to buf then
>does a send_to_char and returns. Now your prestine function that was
>expecting buf to contain something important is now a wash.

Shouldn't you then change that function to use a different variable?
Conflicts are bad, so change them.

(DA: Absurd-O-Matic)

>Marshal Clines C++ FAQ Lite has as section on global variables called
>Just Say No! which says "In fact, you should avoid globals althogether
>whenever you can". Grant you, it's C++ but the rules are relevant here
>(you can view the entire FAQ here, good reference:

Sure, just make a global class instance. :)

>Perhaps a good change, instead of eliminating the global variables, would
>be to create a global.h and global.c which holds all of these. Then
>people could go here and see what is being used instead of trying to
>guess. If anyone has the time maybe try running lint against some of the
>code to see what it says?

It's more fun to make a 'struct global g;' and throw everything in there.

>One additional thought is the use of static variables. In the case where
>the code does share something between functions perhaps it should make
>more use of static variables and especially static function names where
>the function is only used in that one module. Just makes the code tighter
>and better to maintain.

Pass the string in by parameter or static buffer? Personally I'd rather
have the parameter method.

>In any case, most C design books, papers, courses, etc. that I've seen
>usually preach to minimize and/or elminate the use of global variables.
>Is is bad? I don't know but I generally avoid using them when designing
>systems.

"bad" is relative.  Do you use a global variable or pass around 13
different variables you don't care about? I suppose then it becomes a
matter of what IS your design?  I tried to write a program with no global
variables once.  Once it progressed beyond trivial it was quite messy.
There's a difference between file-scoped and global though.  That's
important to keep in mind.

--
George Greer
greerga@circlemud.org

--
   +---------------------------------------------------------------+
   | FAQ: http://qsilver.queensu.ca/~fletchra/Circle/list-faq.html |
   | Archives: http://post.queensu.ca/listserv/wwwarch/circle.html |
   +---------------------------------------------------------------+



This archive was generated by hypermail 2b30 : 12/06/01 PST