🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.std.c++
Article #3634

Question about file-scope constants...

#3634
From: David Held
Date: Mon, 11 Mar 1996 00:38
141 lines
7342 bytes
I was under the impression that a const object of any type and its data
members remained constant throughout their scope (which should be the
whole file, in this case), and that those data members were correctly
accessible from within any function in that scope.  After seeing how
long my post was, I thought I had better get to the point darned quickly
at the beginning. ;>
	I'm using g++ 2.7.2 on a Linux box (which I suppose shouldn't be
important in comp.std.c++, but I thought I'd include it in case someone
knows of an anomaly), and I'm trying to cobble a little exception class
together.  It's really simple, so I'll include some of the declarations
here:

const int Name_Size = 65;

class Exception
{
protected:

  char the_Name[Name_Size];
  static Node *the_List;

public:

  Exception(char *);
  Exception(const Exception &);

  bool operator ==(const Exception &) const;
  bool operator !=(const Exception &) const;

  void Raise(char * = NULL) const;

  static void Entry(char *);
  static void Exit(char *);

};

Now the idea is that for every function, I call Exception::Entry with a
little message giving the name of the function I have entered.  The
Entry function appends a new Node to the end of a linked list pointed to
by the_List.  This Node contains the name in a static size string
(char[65]).  When I encounter a case where I want to raise an exception,
I call Raise with a little message stating the circumstances of the
Exception.  Here's an exampe:

const Exception Memory_Error("Memory Error");

if (!(data = new int[64])) {

  Memory_Error.Raise("Failed memory allocation.");

}

The Raise function goes down the_List, printing the function name in
each Node until it reaches the end.  It then prints the handy-dandy
message, and throws itself (throw(*this)).  If there is an Exception
catcher nearby, the Exception can be handled.  Otherwise, it terminates
the program.  The purpose of my class is to make it easy to debug
programs by locating the exact point where an exception occurs without
stepping through with a debugger.  I can follow the function trail down
the place where the exception was raised. Here's a typical output:

Cursor out of bounds.
Demo:
Show_Menu():
Move_Cursor():
Exception Boundary Error was raised.

Here's my problem: I declare several const Exceptions in the exception.h
file, since they are ones that I expect to use in every program
(Memory_Error, Boundary_Error, File_Error, etc.).  Since I have to
#include "exception.h" in a file to use the exceptions anyway, it makes
sense.  I wrote a demo program where the main body is in a file called
main.cpp, and the exception testing demo is in exception_demo.cpp.  I
have appropriate header files for both, and I include exception.h in
both (I set a meta-variable to make sure exception.h only gets included
once).  Exception_demo.cpp contains the testing function, but apparently
when the program enters this only function of exception_demo.cpp, one of
the exceptions declared in exception.h gets mysteriously modified.  This
is weird, because they are const.  So, in exception.h, I have some const
Exceptions declared thusly:

const Exception
  No_Exception("No Exception"),
  Boundary_Error("Boundary Error"),
  Memory_Error("Memory Error"),
  File_Error("File Error");

When I go to raise No_Exception (i.e.: No_Exception.Raise("Testing");),
the_Name is wrong.  That is, No_Exception.the_Name is not "No
Exception", like it is supposed to be.  Instead, it is " Error\000ption"
followed by 52 ASCII 0's.  At first, I had the_Name allocated
dynamically, inside the Exception constructor, but when I got this
problem, I changed it to static strings.  The problem persisted (I
thought maybe it had something to do with destructors being called or
not having a copy constructor), so now I'm stumped.
	I was under the impression that if you declare a const object of file
scope, with only statically allocated data members, that all of its data
would remain intact within that scope, and that the object would be
visible in any function entered within that scope.  Apparently, someone
is tampering with my data, and it appears that they are breaking the
rules.  There are no assignments to Exception::the_Name after the
constructor is called.  There is no conceivable way that my code could
be modifying the object data.
	There are a few interesting phenomena to note: the first const
Exception is the only one that gets tampered with.  All of the rest of
them remain the same.  I have juggled them around, changed their names,
everything I could think of.  The first one is always the only one that
changes.  When I traced through the code with gdb, No_Exception (which I
used to use when I was passing Exceptions back through functions,
instead of throwing them--didn't have 2.7.2) is fine all the way to the
point where exception_demo.cpp is entered, and void Exception_Demo(void)
is called (all that happens up to then, is you can pick which demo you
want to run through a primitive text menu--no possible interference
here).  During the call to exception_demo.cpp is when
No_Exception.the_Name gets corrupted.  I know this, because I
single-stepped through the code, and inspected No_Exception.the_Name
both before the call, and after the first line of Exception_Demo(void)
(which happens to be an innocent cout statement).  The name appears to
get corrupted during the call.  However, I believe that it is "magically
restored" back in main.cpp.  This indicates to me that some foul copy of
No_Exception is used in exception_demo.cpp (and thus Exception_Demo()).
Is this true?  I have a correct copy constructor defined, so I would
think that even if it made a temporary, that it would do so correctly
(after all, all the other exceptions work fine).
	In summary, I was under the impression that a const object of any type
and its data members remained constant throughout their scope (which
should be the whole file, in this case), and that those data members
were correctly accessible from within any function in that scope.  If
anyone can help me, or clarify the defined actions of C++, I would
greatly appreciate it.

			Sincerely,

			Dave Held.
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your 
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu 
]
Technical Details
Message-ID: <314100A9.41C6@turing.cs.stcloud.msus.edu>
Path: arc1-ca.pugleaf.net!chronicle.mti.sgi.com!austern

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!chronicle.mti.sgi.com!austern
From: David Held <dheld@turing.cs.stcloud.msus.edu>
Newsgroups: comp.std.c++
Subject: Question about file-scope constants...
Date: 10 Mar 1996 16:38:22 PST
Organization: Minnesota State Universities
Approved: austern@isolde.mti.sgi.com
Message-ID: <314100A9.41C6@turing.cs.stcloud.msus.edu>
NNTP-Posting-Host: isolde.mti.sgi.com
X-Original-Date: Fri, 08 Mar 1996 19:53:13 -0800
X-Mailer: Mozilla 2.0 (X11; I; IRIX 5.3 IP22)
X-Auth: PGPMoose V1.1 PGP comp.std.c++
 iQBVAwUBMUN2DUy4NqrwXLNJAQFbTgH9ETx8B0WjlOafcuc8NQoxtq+dARG92may
 374ixZX9qUzHI9KAb8R/m/EqefrYkMNHtotlEhc7q1yeKNVEXS7H/A==
 =hOn6
Originator: austern@isolde.mti.sgi.com