cline@cheetah.ece.clarkson.edu (Marshall Cline) (08/22/90)
`delete p' (where `p' is a pointer to a base class with a *virtual* dtor) ``does the right thing'' (calls the right dtor) based on the actual type of the object pointed to by `p'. But what if Derived is bigger than Base, and `p' points to a bunch of Derived's (ie: p = new Derived[100]). Will delete[] (or delete[100]) find the actual size of the pointed-to objects from the vtable? Or will it get this size from something hidden near *p itself? This information appears to be necessary in order to avoid messing ones pants... class B { //... public: //... virtual ~B(); }; class D : public B { int D_is_bigger_than_B; public: //... ~D(); }; main() { B* p = new D[100]; //... delete [] p; } -- ============================================================================== Marshall Cline / Asst.Prof / ECE Dept / Clarkson Univ / Potsdam, NY 13676 cline@sun.soe.clarkson.edu / Bitnet:BH0W@CLUTX / uunet!clutx.clarkson.edu!bh0w Voice: 315-268-3868 / Secretary: 315-268-6511 / FAX: 315-268-7600 Career search in progress; ECE faculty; research oriented; will send vita. PS: If your company is interested in on-site C++/OOD training, drop me a line! ==============================================================================
jimad@microsoft.UUCP (Jim ADCOCK) (08/28/90)
In article <CLINE.90Aug21134409@cheetah.ece.clarkson.edu> cline@sun.soe.clarkson.edu (Marshall Cline) writes: > main() > { > B* p = new D[100]; > //... > delete [] p; > } C++ will already "do the wrong thing" with any attempts to address the d's referred to by p, thus rendering any problems with delete [] p moot. The right thing is for a compiler to issue a stern warning on the new array statement assigned to an incompatible pointer.
miron@fornax.UUCP (Miron Cuperman) (08/30/90)
jimad@microsoft.UUCP (Jim ADCOCK) writes: >In article <CLINE.90Aug21134409@cheetah.ece.clarkson.edu> cline@sun.soe.clarkson.edu (Marshall Cline) writes: >> B* p = new D[100]; >> delete [] p; >C++ will already "do the wrong thing" with any attempts to address the d's >referred to by p, thus rendering any problems with delete [] p moot. >The right thing is for a compiler to issue a stern warning on the >new array statement assigned to an incompatible pointer. This is not correct. A pointer to an object may be cast to a pointer to a base class of that object. Therefore the above syntax is correct. From what I understand, the C++ implementation must save the length of the array in bytes, and deallocate it accordingly. -- By me: Miron Cuperman <miron@cs.sfu.ca>
ark@alice.UUCP (Andrew Koenig) (08/30/90)
In article <1180@fornax.UUCP>, miron@fornax.UUCP (Miron Cuperman) writes: > jimad@microsoft.UUCP (Jim ADCOCK) writes: > >In article <CLINE.90Aug21134409@cheetah.ece.clarkson.edu> cline@sun.soe.clarkson.edu (Marshall Cline) writes: > >> B* p = new D[100]; > >> delete [] p; > >C++ will already "do the wrong thing" with any attempts to address the d's > >referred to by p, thus rendering any problems with delete [] p moot. > This is not correct. A pointer to an object may be cast to a pointer > to a base class of that object. Therefore the above syntax is correct. Indeed. However, p is being used here as a pointer to the initial element of an array, and that makes all the difference. If you allocate an array of objects, you must free it through a pointer to the same type. Therefore this is illegal: B* p = new D[100]; delete [] p; For that matter, this won't work either: for (int i = 0; i < 100; i++) p[i] = /* something */ ; -- --Andrew Koenig ark@europa.att.com
pcg@cs.aber.ac.uk (Piercarlo Grandi) (09/01/90)
On 30 Aug 90 04:34:52 GMT, miron@fornax.UUCP (Miron Cuperman) said: miron> jimad@microsoft.UUCP (Jim ADCOCK) writes: jimad> In article <CLINE.90Aug21134409@cheetah.ece.clarkson.edu> jimad> cline@sun.soe.clarkson.edu (Marshall Cline) writes: cline> B* p = new D[100]; cline> delete [] p; jimad> C++ will already "do the wrong thing" with any attempts to jimad> address the d's referred to by p, thus rendering any problems jimad> with delete [] p moot. miron> This is not correct. Jim Adcock did not say it explicitly, but you are casting a (D[100]) to a (B *), and so doing you lose two types of information: that we are addressing entities of type D, and 100 of them, because Marshall Cline's assignment is really read by the compiler as: B *p = &((new D[100])[0]); i.e. p becomes a pointer to the zero'th element of the array. This means that it becomes impossible for the compiler to know that when you write p[i] it must implement it as something like '(B *) ((char *) p + i*sizeof (D))'; it will instead transform it to '(B *) ((char *) p + i*sizeof (B))'. The two expression will only be equivalent when i == 0, and only because inheritance is implemented as prefixing. miron> A pointer to an object may be cast to a pointer to a base class miron> of that object. Therefore the above syntax is correct. The syntax is correct. The compiler will also correctly addres *p; anything else is undefined, because all you have is a pointer to a single object. Remember, in C and C++ you are only allowed to do things like *(p + i) if you *know* that p points to an array of object os the same type as *p, and in this case this is not true. miron> From what I understand, the C++ implementation must save the length of miron> the array in bytes, and deallocate it accordingly. The problem as discussed above is not about the size. jimad> The right thing is for a compiler to issue a stern warning on jimad> the new array statement assigned to an incompatible pointer. The right thing would be for the rule that allows a base pointer to a derived class object to be abolished. It has all the insecurity of being too clever with pointers to unions. Same goes for object assignment. If you want to do polymorphism, there are ways to do it within the language, and they are documentedly hazardous. Polymorphism is (conceptually) difficult, and trying to pretend otherwise is not very nice. Another right thing would be to stop pretending that C/C++ really has arrays; C/C++'s array are really just a polite way of reserving memory for a pointer to roam about -- real arrays carry with them a descriptor. We do have something like a[M][N] in C/C++, but then multi dimensional arrays cause lots of trouble in C/C++ and maybe should be simply expunged. This is probably the right course in C++, which has mechanisms to define within the language proper, descriptor based, arrays. -- Piercarlo "Peter" Grandi | ARPA: pcg%uk.ac.aber.cs@nsfnet-relay.ac.uk Dept of CS, UCW Aberystwyth | UUCP: ...!mcsun!ukc!aber-cs!pcg Penglais, Aberystwyth SY23 3BZ, UK | INET: pcg@cs.aber.ac.uk
jimad@microsoft.UUCP (Jim ADCOCK) (09/05/90)
In article <1180@fornax.UUCP| miron@fornax.UUCP (Miron Cuperman) writes: |jimad@microsoft.UUCP (Jim ADCOCK) writes: | |>In article <CLINE.90Aug21134409@cheetah.ece.clarkson.edu> cline@sun.soe.clarkson.edu (Marshall Cline) writes: |>> B* p = new D[100]; |>> delete [] p; | |>C++ will already "do the wrong thing" with any attempts to address the d's |>referred to by p, thus rendering any problems with delete [] p moot. |>The right thing is for a compiler to issue a stern warning on the |>new array statement assigned to an incompatible pointer. | |This is not correct. A pointer to an object may be cast to a pointer |to a base class of that object. Therefore the above syntax is correct. |From what I understand, the C++ implementation must save the length of |the array in bytes, and deallocate it accordingly. You did not read what I said. I said any attempts to *address* the d's referred to by p will cause "the wrong thing" to happen. The ability to cast to a base class pointer is a far different thing from being able to address an array of Ds as if they were an array of Bs. Calling delete [] p for an array of Ds with p a B*, will typically cause some number of B destructors to be invoked -- which is presumably not what the programmer intended. Compilers will accept this syntax, and generate code other than what the programmer presumably intended. I consider this a weakness in the C++ type system -- which is best plugged by a compiler issuing a warning: "Do you really want me to generate this nonsensible code?"
peb@Autodesk.COM (Paul Baclaski) (09/20/90)
In article <1180@fornax.UUCP>, miron@fornax.UUCP (Miron Cuperman) writes: > jimad@microsoft.UUCP (Jim ADCOCK) writes: > > >In article <CLINE.90Aug21134409@cheetah.ece.clarkson.edu> cline@sun.soe.clarkson.edu (Marshall Cline) writes: > >> B* p = new D[100]; > >> delete [] p; > ... Therefore the above syntax is correct. > From what I understand, the C++ implementation must save the length of > the array in bytes, and deallocate it accordingly. This is not true of V1.2 of cfront, but is true for 2.1. I am not sure about 2.0. C++ *is* converging on the "right way", but it does take time. Paul E. Baclaski peb@autodesk.com