[comp.lang.c++] new/dispose behavior

kevin@msa3b.UUCP (Kevin P. Kleinfelter) (04/29/91)

I'm reading along in a book about C++, and I see that one can do:

   char *s;
   s = new char [40];
   ...
   delete s;

The book then goes on to say that one should:

   int *p;
   p = new int [40];
   ...
   delete 40 p;

These examples seem to suggest to me that one specifies the number of bytes
to delete with int pointers but not char pointers.
Either I'm confused or the book is!

True or False: If one wants to delete all of the 'new-ed' storage one need
               not specify the quantity to delete, just the pointer to the
               storage.
-- 
Kevin Kleinfelter @ Dun and Bradstreet Software, Inc (404) 239-2347
...gatech!nanovx!msa3b!kevin
Warning: There seem to be multiple 'msa3b' nodes on Usenet, and it is
nanoVX, not nanovAx.

pal@xanadu.wpd.sgi.com (Anil Pal) (05/01/91)

In article <1619@msa3b.UUCP>, kevin@msa3b.UUCP (Kevin P. Kleinfelter) writes:
|> I'm reading along in a book about C++, and I see that one can do:
|> 
|>    char* s = new char [40];
|>    delete s;
|> 
|>    int *p = new int [40];
|>    delete 40 p;
|> 
|> Either I'm confused or the book is!

Actually, both of these examples are incorrect as of the latest draft
of the C++ standard.  The correct way (for both cases) is:

    mumble* x = new mumble[40];
    delete [] x;

Earlier implementations of C++ (for example, those based on cfront 2.0 or
before) required the programmer to explicitly supply the count (40) in the
delete.

What happens if you forget and do a simple delete x; ?  Well, for the
examples quoted (int and char) usually nothing dramatic.  The full
storage will probably be returned to the free pool (in typical
malloc/free based implementations).  If the type mumble is a class with
a destructor, however, forgetting the array form of the delete will
result in a single destructor being called, for the 0-th element in the
array.  Using the array syntax (delete [] x;) will correctly call the
destructor for all elements of the array.

-- 
Anil A. Pal,	Silicon Graphics, Inc.
pal@wpd.sgi.com	(415)-335-7279

rmartin@clear.com (Bob Martin) (05/01/91)

In article <1619@msa3b.UUCP> kevin@msa3b.UUCP (Kevin P. Kleinfelter) writes:
>I'm reading along in a book about C++, and I see that one can do:
>
>   char *s;
>   s = new char [40];
>   ...
>   delete s;
>
>The book then goes on to say that one should:
>
>   int *p;
>   p = new int [40];
>   ...
>   delete 40 p;
>
>True or False: If one wants to delete all of the 'new-ed' storage one need
>               not specify the quantity to delete, just the pointer to the
>               storage.

Kevin:

In the ARM section 5.3.4 there is a discussion about delete and arrays.
You must use the form delete [] otherwise the operation is "undefined"
and you will probably encounter odd execution errors.

	char *s;
	s = new char [40];
	...
	delete [] s;

And the same goes for ints, longs, doubles, classes, etc.  So the answer
to your query is "True" but with the added qualifier that when deleting
an array one must use the delete [] form of the operator.



-- 
+-Robert C. Martin-----+:RRR:::CCC:M:::::M:| Nobody is responsible for |
| rmartin@clear.com    |:R::R:C::::M:M:M:M:| my words but me.  I want  |
| uunet!clrcom!rmartin |:RRR::C::::M::M::M:| all the credit, and all   |
+----------------------+:R::R::CCC:M:::::M:| the blame.  So there.     |

jimad@microsoft.UUCP (Jim ADCOCK) (05/16/91)

In article <2210002@hpfelg.HP.COM> greg@hpfelg.HP.COM (Greg Begay) writes:
|>True or False: If one wants to delete all of the 'new-ed' storage one need
|>               not specify the quantity to delete, just the pointer to the
|>               storage.
|>-- 
|
|True if the pointer is to storage containing homogenious data (ie, one type
|of data).  What if you want to free the storage of an array of objects?
|How will the compiler know to call the destructors (and how many
|destructors to call) for the objects in the array?

I disagree -- in theory.  ARM page 64 calls for programmers to use:

delete [] ptrthingee

where ptrthingee is some kind of an expression referring to some kind
of array allocated via new.

and programmers to use:

delete ptrthingee

where ptrthingee is some kind of an expression referring to some kind of
individual item allocated via new.

However, in practice, C++ compiler implementations today vary so widely
in what they expect that all one can do is experiment and try to discover
the behavior of one's compiler.  Many implementations are "busted" in one way
or another, so be prepared for the unexpected.

The language could have been designed such that the allocation routines
were required to keep track of how many objects [1 to N] are being
allocated, what size and types those objects are, etc, but this was
considered to be too much overhead.  By requiring programmers to specify
the [] when deleting arrays, implementors are given the option of using
separate allocation schemes for arrays vs individual objects -- with the
remembering number of elements allocated [and hence needing to be 
destroyed] only required for array allocations.  Also, implementations
might want to specialize their allocation schemes under the assumption
that individual object allocations are typically quite small, whereas
array allocations can be quite big.

Unfortunately, all this comes down to inherent problems with the 
multiple overloaded meanings of a "pointer" in C/C++:

1) a reference to an individual object or
2) a reference to an array or
3) a reference to a start of an array or
4) a reference to an element in an array or
5) a reference to whatever would be one past the end of an array if such
	object actually existed or
6) a byte address of what programmers typically mistakenly refer to as
	physical memory but which is actually, usually, a reference to a
	virtual address of a relocatable group of bytes, said fact
	cleverly hidden from some programmers in some simple situations
	via a complicated system of software/firmware/hardware, and 
	not hidden at all from programmers in more complicated situations,
	such as those doing "object oriented programming."

This situation could have been somewhat repaired had C++ provided enough
power to C++ "references" that they could have been commonly used instead
of pointers.  But, this is presumably water under the bridge.