Topic: Proposal: keep sizeof in vtable


Author: ben-public-nospam@bwsint.com (Ben Hutchings)
Date: Wed, 11 Feb 2004 04:55:27 +0000 (UTC)
Raw View
"Rafal Dabrowa" wrote:
> "Ben Hutchings" wrote:
>> sizeof expressions are currently integer constant expressions.  The
>> change you suggest would prevent some of them from being evaluated at
>> compile-time or would cause some of them to have different values
>> depending on whether they are evaluated at compile-time or run-time.
>> That is not likely to be an acceptable change.
>
> Why not ? C99 standard has "variable length arrays". For these
> arrays, sizeof expression is not a constant.

Those are new types and there is not the same compatibility issue.
Nevertheless I think it's a mistake that we should not copy.  C++ has
tended to gain general powerful features that allow for the
implementation of specific features as libraries, rather than tacking
on ad-hoc FORTRAN-isms as C99 did.  Why not use them?

<snip>
> Program has no trouble with find proper virtual function. Also,
> it has no trouble with get proper type_info.
> So, why expect problems with find proper object size ?

It's possible, but I think what you want to do is questionable
programming anyway.  It is not the case that an array of derived-class
IS-A array of base-class, so the conversion shouldn't be allowed.  See
<http://www.parashift.com/c++-faq-lite/proper-inheritance.html#faq-21.3>.
If you want to store instances of derived-class in an array of base-
class, you should really be using an array of pointers.

--
Ben Hutchings
If at first you don't succeed, you're doing about average.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: rdsbrows@nospam.onet.pl (Rafal Dabrowa)
Date: Sun, 15 Feb 2004 21:31:27 +0000 (UTC)
Raw View
Ben Hutchings wrote:

> It's possible, but I think what you want to do is questionable
> programming anyway.  It is not the case that an array of derived-class
> IS-A array of base-class, so the conversion shouldn't be allowed.

But *it is* allowed. Compiler does not complain. The trouble begins
at run-time.
        The main mistake at C/C++ design was to not differentiate
between pointer to object and pointer to array of objects. This worked
fine in C, but went into trouble in C++. I have proposed the trouble
workaround, unfortunately it is not a good solution.

> See
> <http://www.parashift.com/c++-faq-lite/proper-inheritance.html#faq-21.3>.
> If you want to store instances of derived-class in an array of base-
> class, you should really be using an array of pointers.

OK, suppose the following code:

class A {/* ... */ };
class B : public A {/* ... */ };
class C : public A {/* ... */ };

A *pA1 = new B;
A *pA2 = new C;

*pA1 = *pA2;    // Oops...

Do you see something wrong in this code ? Object of class C is assigned
to an object of class B. This is allowed in C++. Compiles fine, even
without any warning. Why ? In the same way, I can have an array of
B under pA1 and an array of C under pA2, and assign:

        pA1[3] = pA2[7];

Why not ? If somebody wants to assign in this way... I don't want.
But, I want to create a function, like this:

void f(const A *pAtab, int count) { /* ... */ }

and pass to this function both an array of B objects, and an array of
C objects. Do you see something wrong here ?
        I can't do that in any way. Even with an array of pointers,
which you have mentioned.


Rafal
--
sed -e s/s/a/g <my_address >my_right_address

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: rdsbrows@nospam.onet.pl ("Rafal Dabrowa")
Date: Thu, 5 Feb 2004 22:08:43 +0000 (UTC)
Raw View
Suppose the following code:

    class C {
        // ... - members
    public:
        void fun() { /* ... */ }
        virtual ~C() {}
    };

    class D : public C { /* ... */ };

    int main()
    {
        C *pC = new D[10];
        pC[3].fun();    // Oops: runtime error
        delete[] pC;    // Oops: another runtime error
    }

The above code compiles fine. But, there is a problem:
"this" pointer passed to fun() is bad, because it is calculated
based on sizeof(C). Maybe keep actual size of structure together
with virtual function table ? It would be used in arithmetic pointers
operations. Also, sizeof(*pC) might return actual object size.


Rafal
--
sed -e s/s/a/g <my_address >my_right_address


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: brok@rubikon.pl (Bronek Kozicki)
Date: Fri, 6 Feb 2004 15:46:30 +0000 (UTC)
Raw View
On Thu, 5 Feb 2004 22:08:43 +0000 (UTC), "Rafal Dabrowa" wrote:
>         C *pC = new D[10];
>         pC[3].fun();    // Oops: runtime error
>         delete[] pC;    // Oops: another runtime error

Rafal, you have undefined behaviour here per clause 5.3.5/2 of C++
standard:

"In the second alternative (delete array), the value of the operand of
delete shall be the pointer value which resulted from a previous array
new-expression.72) If not, the behavior is undefined."

You may not cast array to pointer to base type of array element. If you
do, compiler won't know at compile time correct size of array element
and address of its destructor; it will use wrong data instead. The same
applies to array element dereference. I hope that explains both errors
you are experiencing; if you want to propose change of this behaviour,
you need to know that it will impose substantial changes to C++
compilers, thus is very unlikely to be accepted. Especially as there is
well-known and cheap workaround for this problem - avoid using C arrays
in C++ code, and use std::vector instead.


B.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: do-not-spam-benh@bwsint.com (Ben Hutchings)
Date: Fri, 6 Feb 2004 19:13:12 +0000 (UTC)
Raw View
"Rafal Dabrowa" wrote:
> Suppose the following code:
>
>     class C {
>         // ... - members
>     public:
>         void fun() { /* ... */ }
>         virtual ~C() {}
>     };
>
>     class D : public C { /* ... */ };
>
>     int main()
>     {
>         C *pC = new D[10];
>         pC[3].fun();    // Oops: runtime error
>         delete[] pC;    // Oops: another runtime error
>     }
>
> The above code compiles fine. But, there is a problem:
> "this" pointer passed to fun() is bad, because it is calculated
> based on sizeof(C). Maybe keep actual size of structure together
> with virtual function table ? It would be used in arithmetic pointers
> operations. Also, sizeof(*pC) might return actual object size.

sizeof expressions are currently integer constant expressions.  The
change you suggest would prevent some of them from being evaluated at
compile-time or would cause some of them to have different values
depending on whether they are evaluated at compile-time or run-time.
That is not likely to be an acceptable change.

Possibly compilers should warn about assignment expressions that
assigns the result of an array-new to a pointer of a different type.
However, those errors should be fairly obvious to the programmer;
I suspect the greater risk is from later conversions which may be
just as hard for the compiler to spot as for the programmer.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: ark@acm.org ("Andrew Koenig")
Date: Sat, 7 Feb 2004 01:54:38 +0000 (UTC)
Raw View
> Maybe keep actual size of structure together
> with virtual function table ? It would be used in arithmetic pointers
> operations. Also, sizeof(*pC) might return actual object size.

One potentially serious problem with this idea is that it is possible for a
pointer to point one past the end of an array.  For example:

    class Foo { /* ... */ };

    Foo* fp = new Foo[10];
    fp += 10;

Now fp is not pointing to an object.  Nevertheless, it is possible to cause
fp to point to an object by subtracting an integer from it.  This
subtraction requires the implementation to know the size of a Foo object.
If this information were available only through the vtable, there would be
no way to obtain it to do the subtraction.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: rdsbrows@nospam.onet.pl ("Rafal Dabrowa")
Date: Sat, 7 Feb 2004 07:56:31 +0000 (UTC)
Raw View
"Ben Hutchings" wrote:
> sizeof expressions are currently integer constant expressions.  The
> change you suggest would prevent some of them from being evaluated at
> compile-time or would cause some of them to have different values
> depending on whether they are evaluated at compile-time or run-time.
> That is not likely to be an acceptable change.

Why not ? C99 standard has "variable length arrays". For these
arrays, sizeof expression is not a constant.

> Possibly compilers should warn about assignment expressions that
> assigns the result of an array-new to a pointer of a different type.
> However, those errors should be fairly obvious to the programmer;
> I suspect the greater risk is from later conversions which may be
> just as hard for the compiler to spot as for the programmer.

Program has no trouble with find proper virtual function. Also,
it has no trouble with get proper type_info.
So, why expect problems with find proper object size ?


Rafal
--
sed -e s/s/a/g <my_address >my_right_address


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: rdsbrows@nospam.onet.pl ("Rafal Dabrowa")
Date: Sat, 7 Feb 2004 17:57:40 +0000 (UTC)
Raw View
Andrew Koenig wrote:
> One potentially serious problem with this idea is that it is possible for
a
> pointer to point one past the end of an array.  For example:
>
>     class Foo { /* ... */ };
>
>     Foo* fp = new Foo[10];
>     fp += 10;
>
> Now fp is not pointing to an object.  Nevertheless, it is possible to
cause
> fp to point to an object by subtracting an integer from it.  This
> subtraction requires the implementation to know the size of a Foo object.
> If this information were available only through the vtable, there would be
> no way to obtain it to do the subtraction.


Yes, this is a problem. Also, there is a problem with take sizeof(*T) for
null pointers, or for dangling pointers. Also, there is a problem with
backward compatibility of sizeof operator. Maybe this is not a good idea.


Rafal
--
sed -e s/s/a/g <my_address >my_right_address


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]