Topic: compile-time error message, please!


Author: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Date: Tue, 18 Jan 1994 19:15:22 GMT
Raw View
jvsb@ra.alcbel.be (Johan Vanslembrouck) writes:

>In the first example (p1), it is even impossible to recalculate the
>original pointer value because casting from a virtual base class
>to a derived class is disallowed.

Casting from a virtual base class to a derived class is now possible
using the RTTI extensions, I believe.

>That's why I would prefer a
>compile-time error here. In the case of a non-virtual base class,
>a warning may be sufficient.

I think that a warning would probably be a good idea in all of these cases,
but the language should not mandate a compile-time error in any of them.

--
Fergus Henderson        |   "People who brook no compromise in programming
                        |   languages should program in lambda calculus or
fjh@munta.cs.mu.OZ.AU   |   machine language, depending." --Andrew Koenig.




Author: jvsb@ra.alcbel.be (Johan Vanslembrouck)
Date: 19 Jan 94 08:59:19 GMT
Raw View
In <2hegkdINNkiv@early-bird.think.com> barmar@think.com (Barry Margolin)
writes:

> In article <1994Jan17.110433@ra.alcbel.be> jvsb@ra.alcbel.be (Johan
> Vanslembrouck) writes:
>> Base1 *p1 = new Derived1; // compile-time error, please!
>> delete p1;   // p1 not at start of allocated block
>
> How should the compiler know to generate an error for this?  Presumably it
> should also generate the same error for:
>
> Base1 *function();
> Base1 *p1 = function();
> delete p1;
>
> since function() could return a Derived*.

"function" will probably contain a statement like:

 return new Derived;

I would only prefer an error or warning message at the statement containing
the "new" to protect the programmers against accidents.

Like is mentioned somewhere in the ARM: the compiler should protect the
programmer
against accidents, not against fraude, like in:

 Derived* p1 = new Derived; // OK
 p1++;
 delete p1;

I had a program here with a lot of statements like

 Base* p = new Derived1;
 Base* p = new Derived2;
 ...

at different locations in my program.
Every Derivedi was indirectly non-virtually derived from Base. It
worked
fine. Then I decided to make Base a virtual base class. You can guess
what happened. Core dumps all over the place. I had to find all
locations
in the program where I had such "new" statements. It would have been
better if the compiler could have marked these statements as
errors or warnings.

-----------------------------------------------------------

Other question:
Is it true that the following example causes troubles?

main()
{
 Base* p = new Derived;
 delete p;
}

even when Derived is non-virtually derived from Base
and when Base is its only or first base class
BUT when the size of Derived is larger than that of Base
and when no virtual destructor is provided by Base?

If so, the compiler could easily complain about this!
Searching memory leaks in a large program is a very hard task.
Most people will suffice by looking up new-delete pairs and think
everything is all right.





-----------------------------------------------------------------------
Johan Vanslembrouck - SE99                 Tel    : +32 3 2407739
Alcatel Bell Telephone                     Telex  : 72128 Bella B
Francis Wellesplein  1                     Fax    : +32 3 2409932
B-2018 Antwerp                             e-mail : jvsb@ra.alcbel.be
Belgium
-----------------------------------------------------------------------




Author: jvsb@ra.alcbel.be (Johan Vanslembrouck)
Date: 17 Jan 94 10:04:33 GMT
Raw View
The following program contains 2 errors, because "delete" will not
be able to free an allocated block of memory.

-------------------------------------------------------------------------

class Base1 { int i1; };

class Base2 { int i2; };

class Derived1 : public virtual Base1 { };

class Derived2 : public Base1, public Base2 { };

main()
{
 Base1 *p1 = new Derived1; // compile-time error, please!
 delete p1;   // p1 not at start of allocated block

 Base1* p2 = new Derived2;
 delete p2;

 Base2* p3 = new Derived2; // compile-time warning, please!
 delete p3;   // p3 not at start of allocated block

 Base2* p4 = new Derived2; // compile-time warning, please!
 delete (Derived2 *) p4;  // OK
}

-------------------------------------------------------------------------

The reason is that the implicit casting of 'a pointer to an
object of a derived class' to 'a pointer to an object of a base class'
may change the value of the pointer. This is the case in 3 of the examples.
In the first example (p1), it is even impossible to recalculate the
original pointer value because casting from a virtual base class
to a derived class is disallowed. That's why I would prefer a
compile-time error here. In the case of a non-virtual base class,
a warning may be sufficient.

Who is in favor of this proposal? Telling the programmer at compile-time
what happens is much better than causing a segmentation fault. The latter
is too much C-like.


-----------------------------------------------------------------------
Johan Vanslembrouck - SE99                 Tel    : +32 3 2407739
Alcatel Bell Telephone                     Telex  : 72128 Bella B
Francis Wellesplein  1                     Fax    : +32 3 2409932
B-2018 Antwerp                             e-mail : jvsb@ra.alcbel.be
Belgium
-----------------------------------------------------------------------




Author: barmar@think.com (Barry Margolin)
Date: 17 Jan 1994 17:07:25 GMT
Raw View
In article <1994Jan17.110433@ra.alcbel.be> jvsb@ra.alcbel.be (Johan Vanslembrouck) writes:
> Base1 *p1 = new Derived1; // compile-time error, please!
> delete p1;   // p1 not at start of allocated block

How should the compiler know to generate an error for this?  Presumably it
should also generate the same error for:

 Base *function();
 Base1 *p1 = function();
 delete p1;

since function() could return a Derived*.  What this effectively means is
that delete must be disallowed for any pointer for which flow analysis
can't prove that it holds an object of the static type.  This would rule
out for global pointers, since they could be assigned by another module.

And suppose you moved the delete statement into a virtual function, so that
it would operate on the appropriate object.  How could the compiler know
that the delete should be allowed there?  It's possible that the most
derived class doesn't redefine the function, so it ends up being done in an
intermediate class, which would be wrong.  Therefore, the compiler still
can't allow the delete!
--
Barry Margolin
System Manager, Thinking Machines Corp.

barmar@think.com          {uunet,harvard}!think!barmar




Author: pkt@lpi.liant.com (Scott Turner)
Date: Mon, 17 Jan 1994 19:04:58 GMT
Raw View
In article <1994Jan17.110433@ra.alcbel.be>, jvsb@ra.alcbel.be (Johan
Vanslembrouck) wrote:

> The following program contains 2 errors, because "delete" will not
> be able to free an allocated block of memory.
>
> class Base1 { int i1; };
> class Base2 { int i2; };
> class Derived1 : public virtual Base1 { };
> class Derived2 : public Base1, public Base2 { };
>
>  Base1 *p1 = new Derived1; // compile-time error, please!
>  delete p1;   // p1 not at start of allocated block

>  Base2* p3 = new Derived2; // compile-time warning, please!
>  delete p3;   // p3 not at start of allocated block

These circumstances seem suitable for a compile-time warning.

Note that if a virtual destructor is added to Base1 and Base2,
then the 'delete' statements will function as desired, despite the
peculiarities of base class pointer implementation, in which they
may become offset from the full object.
--
Scott Turner
Liant Software Corp.
959 Concord St., Framingham, MA 01701  USA
(508)872-8700
pkt@lpi.liant.com