[comp.lang.c++] cfront feature or bug?

neath@solar-1.stars.flab.Fujitsu.JUNET (05/04/89)

I have just spent an hour trying to find out why my Vector class implementation
was  core dumping.  It turns out  that  the C++  variable declaration mechanism
whereby declarations can  get moved around and/or  performed in a new block can
result in some problems.  Look at the following code fragment:
  
        class X {
          int i;
        public:
	  X() {};
          X(int n) { i = n; }
          void times_two () {i *= 2;}
        };

        void dummy (int k) {
          int i;
          if (k > 3)
	    X* t = new X[10];
          else
	    X* t = new X[20];
	  t.times_two();
        }

At a first glance, this   code  seems to be  OK.  The pointer variable  "t"  is
declared in one of  two ways depending upon  the  value of variable "k". If you
compile this, you get a "error: two declarations of t"  message from cfront.
This is because cfront generated two empty declaration statements "X* t" in the
outer body with specific initialization code in the "if" and "else" clauses. An
even worse problem (and the one that was affecting my code) is shown below:

        class X {
          int i;
        public:
	  X() {};
          X(int n) { i = n; }
          void times_two () {i *= 2;}
        };

        void dummy (int k) {
          int i;
          if (k > 3) {
            ::: // some code here
	    X* t = new X[10];
            ::: // more code here
          }
          else
	    X* t = new X[20];
	  t.times_two();
        }

What happens if the "k > 3" test is  TRUE? Well, not what  you think! Since the
code contained in the body  of  the if  statement is surrounded by braces,  the
variable declaration of "t" is lexically scoped to this inner block.  Now, that
would not be  so bad if that was  the only place that had  a declaration, since
any attempt to use "t" outside of that block  would result in  a  "variable not
declared" error.

However, because of the second declaration of "t" in the "else" clause, no such
thing happens. The reason is that cfront places an  empty declaration of "t" in
the outer body, then initializes it in the "else" clause.  If "k >  3" is TRUE,
then the inner-block "t" is declared and initialized. At the end of this block,
this "t" falls out of scope, and future references to "t" get the uninitialized
outer-block variable. This, of course, is a NULL  pointer that, when first used
in the code, will kindly result in a bus error or some other nasty thing :-(

My questions are: 1) Is this a bug in cfront?
                  2) If it is a bug, is it fixed in 2.0?

Regards
Martin Neath <neath@dsg.ti.com>
------------------------------------------------------------------------
 DISCLAIMER: As always, the opinions expressed above are strictly my own
 and do not reflect those of my employer, Texas Instruments.
------------------------------------------------------------------------

ark@alice.UUCP (Andrew Koenig) (05/06/89)

In article <NEATH.89May4105353@solar-1.stars.flab.Fujitsu.JUNET>, neath@solar-1.stars.flab.Fujitsu.JUNET writes:

>           if (k > 3)
> 	    X* t = new X[10];
>           else
> 	    X* t = new X[20];

Cfront 2.0 will give an error message if you try to make a
declaration the (only) subject of an if or else clause.

It is far from clear what something like this should mean:

	if (x > 0)
		int y;

Clearly, this cannot conditionally declare y in the surrounding
context: how could one possibly compile this:

	if (x > 0)
		int y;
	y++;

If you really want the declaration to live in a block of its own,
you can still write

	if (x > 0)
		{ int y; }

and your meaning is then clear.
-- 
				--Andrew Koenig
				  ark@europa.att.com

mat@mole-end.UUCP (Mark A Terribile) (05/07/89)

> I have just spent an hour trying to find out why my Vector class
> implementation was core dumping.  ...
   
_>         class X {
_>           int i;
_>         public:
_> 	  X() {};
_>           X(int n) { i = n; }
_>           void times_two () {i *= 2;}
_>         };
 
_>         void dummy (int k) {
_>           int i;
_>           if (k > 3)
_> 	    X* t = new X[10];
_>           else
_> 	    X* t = new X[20];
_> 	  t.times_two();
_>         }
 
> At a first glance, this   code  seems to be  OK.

Eh?  Try

	X* t = ( k > 3 ) ? new X[ 10 ]
			 : new X[ 20 ] ;

> ... An even worse problem ...

_>         void dummy (int k) {
_>           int i;
_>           if (k > 3) {
_>             ::: // some code here
_> 	    X* t = new X[10];		// <== Wrong scope, fershure ...
_>             ::: // more code here
_>           }
_>           else
_> 	    X* t = new X[20];
_> 	  t.times_two();
_>         }
 
> My questions are: 1) Is this a bug in cfront?
>                   2) If it is a bug, is it fixed in 2.0?

More likely, it's a weakness in the language.  This is one of those places
where you really ought to declare the variable and initialize it later, I
think.
-- 

(This man's opinions are his own.)
From mole-end				Mark Terribile