Topic: Just one more library function


Author: clamage@Eng.sun.com (Steve Clamage)
Date: 1996/04/23
Raw View
In article 5CAA@cds.duke.edu, Max TenEyck Woodbury <mtew@cds.duke.edu> writes:
>Steve Clamage wrote:
>>
>> I'd also like to point out that if you need to query an array about its
>> size, you probably should not be using a C-style array, but an array
>> class instead.
>>
>> Finally, the proposal mentions only arrays on the heap. Is it the case that
>> you care about the size only of arrays allocated with operator new[],
>> and not static arrays? What about:
>>         extern T myarray[]; // how big is it?
>>
>> If you use an array class, you can get the functionality you want, and
>> don't necessarily have to pay for functionality you don't want. If you
>> use the standard vector class, you don't even have to write any code.
>
>The purpose of such a function could be to simplify the implementation of
>an array class.  The information is available in one form or another to the
>delete operator if needed.  Making the same information available to the
>class designer in a consistant form would reduce execution overhead, not
>increase it. It would require compiler support of some form, just as the
>delete operator requires compiler support.
>
>The proposal dealt specifically with dynamic allocation.  Dragging in
>static allocation changes the proposal.  There are ocasions when it is
>difficult, if not impossible, to distinguish between static and dynamic
>allocation.  Those dificulties already have consequences in the language,
>specifically in defining the behavior of the delete operator and the
>free() function, so the proposal will not introduce more than minor
>variations on existing problems.  Therefore the arguments about static
>allocations are mainly irrelavant.

I'm afraid I don't see what you are getting at.

If you create an array class it must keep track of its size. Presumably
it uses some forms of new and delete for memory management. In the general
case, the array element type might not have a destructor, in which case
the typical implementation of "new[]" does not keep track of the
number of elements. It is also more likely for an array class to allocate
raw memory via "operator new()" than to use "new T[count]". If type T does
not have a default constructor, you cannot use "new T[count]" anyway. If
you want to allow the possibility of unused array slots, you could not
delete the array with "delete[]" even if you did allocate it with "new[]".

So you are asking for a special language feature to provide the number
of elements of an array allocated on the heap. The function has a potential
benefit only for code that uses C-style arrays on the heap of types that have
a default constructor. How a programmer is to know whether it is safe to call
the function or what happens if it is called anyway hasn't been discussed yet.

For example: Function f has a parameter of type T*, which points to the start
of a C-style array. Can f find out how big the array is? Is it always safe to
ask? What will f do if the answer comes back "size not available"?

In short, I see very little utility in such a feature, but it would burden
every heap array with an element count, whether the programmer wanted it or not.

I don't even see that the feature would make it easier to implement an
array class. If you have to query the size, why is it less trouble to call
a built-in function than to access a class member? The only thing you save
is initializing the "count" member in each constructor.

What is the cost of the status quo? If you want to keep track of the size
of an array, you must do so explicitly, at a cost of one word per array object.
This extra word might duplicate information that the system keeps anyway.
I claim that for a typical array class there is no duplication of data, so
the waste is zero. And those who do not need the feature do not pay for it.

---
Steve Clamage, stephen.clamage@eng.sun.com




[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: dougm@rice.edu (Doug Moore)
Date: 1996/04/24
Raw View
Steve Clamage (clamage@Eng.sun.com) wrote:
: In article 5CAA@cds.duke.edu, Max TenEyck Woodbury <mtew@cds.duke.edu> writes:
: >The purpose of such a function could be to simplify the implementation of
: >an array class.  The information is available in one form or another to the
: >delete operator if needed.  Making the same information available to the
: >class designer in a consistant form would reduce execution overhead, not
: >increase it. It would require compiler support of some form, just as the
: >delete operator requires compiler support.
: >
: >The proposal dealt specifically with dynamic allocation.  Dragging in
: >static allocation changes the proposal.  There are ocasions when it is
: >difficult, if not impossible, to distinguish between static and dynamic
: >allocation.  Those dificulties already have consequences in the language,
: >specifically in defining the behavior of the delete operator and the
: >free() function, so the proposal will not introduce more than minor
: >variations on existing problems.  Therefore the arguments about static
: >allocations are mainly irrelavant.

: I'm afraid I don't see what you are getting at.

There are several pieces of information already hidden in the
implementation of builtin arrays.  One is the number of items in the
array, if the array is of a type that has a destructor.  Since that
number is not stored for all arrays, I won't request it.

However, another number that is stored for all arrays is the size of
the space allocated for the array.  The memory manager must have that
information.  As a potential implementor of an Array class, I would
like to know, when I ask for an array of size 27, how much space is
actually avaiable in the array.  Internal fragmentation is likely.  If
I offered a function Array::resize, I would like to know whether or
not I need to expand the space available for the array.  If my request
for 27 characters actually caused memory for 32 characters to be set
aside, and I seek to grow the array only 3 characters bigger, then I
don't need to allcocate, copy, and delete.  I can just extend in
place.

The information is there, but I cannot portably get it.  The interface
to free store management is unfortunately very crude.  I should be
able to find out the amount of space in the current block, and I
should be able to find out how large a reallocation I could do without
needing to copy data.  Right now, if I want all these things, I have
to reimplement malloc.

: For example: Function f has a parameter of type T*, which points to the start
: of a C-style array. Can f find out how big the array is? Is it always safe to
: ask? What will f do if the answer comes back "size not available"?

Can we find out how much storage is set aside for the array?  Yes,
just not portably.

--
Doug Moore
Research Scientist/Lecturer
Computer Science/Computational and Applied Math
(dougm@rice.edu)
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 1996/04/25
Raw View
dougm@rice.edu (Doug Moore) writes:

>However, another number that is stored for all arrays is the size of
>the space allocated for the array.  The memory manager must have that
>information.  As a potential implementor of an Array class, I would
>like to know, when I ask for an array of size 27, how much space is
>actually avaiable in the array.

But that information is not available for static or auto objects.
Even a member function of a class cannot in general know whether
the object is on the heap or not.

Consider a built-in language feature "actual_size" that returns the
amount of storage available:

 T1 foo(T2* p) // some function
 {
  size_t sz = actual_size(p);
  ... do something with sz
 }

Are we assured of a meaningful answer if the object is not on the
heap? If not, the facility is useless. If so, every static and auto
object must be augmented by the system with additional information to
show it is not on the heap. (Substitute "this" for "p" above and
the situation is the same.)

And what if 'p' points into the middle of an array? Are we still
assured of a meaningful answer? How? And if not, is this really
such a useful feature?

Then we have to decide what to do about user-written "operator new"
functions. How can the system still be assured of finding a
meaningful result for the actual_size function? For example:

 void* operator new(size_t sz) // or operator new[]()
 {
  static long double data[100000];
  static void* p = data;
  if( <not enough room> ) throw bad_alloc();
  <increment p by sz rounded up>;
  return p;
 }

How will the actual_size function work reliably? We'd have to
specify an implementation technique for it, and require a
user-written operator new to use that technique.

This is an awful lot of mechanism, and adds penalties to every C++
program ever written on any system, just to make available something
that might not even turn out to be useful. (See my earlier article.)

The alternative is for you to keep track of the size when you need
it, and risk wasting one word of storage for each array object.
--
Steve Clamage, stephen.clamage@eng.sun.com
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: dougm@rice.edu (Doug Moore)
Date: 1996/04/26
Raw View
Steve Clamage (clamage@Eng.Sun.COM) wrote:
: dougm@rice.edu (Doug Moore) writes:

: >However, another number that is stored for all arrays is the size of
: >the space allocated for the array.  The memory manager must have that
: >information.  As a potential implementor of an Array class, I would
: >like to know, when I ask for an array of size 27, how much space is
: >actually avaiable in the array.

: But that information is not available for static or auto objects.
: Even a member function of a class cannot in general know whether
: the object is on the heap or not.

Of course not.  But then, a member function can't know either whether
or not it is safe to delete the object.  *Obviously* we're talking
about dynamic memory alloctation here.  *Obviously* there are things
you can do to dynamically allocated memory that you can't do with
statically or automatically allocated memory.  That's already true.
Adding a feature that relates only to dynamically allocated memory
does not change the fact the a programmer must often know the origin
of the memory with which he is working.

: Consider a built-in language feature "actual_size" that returns the
: amount of storage available:

:  T1 foo(T2* p) // some function
:  {
:   size_t sz = actual_size(p);
:   ... do something with sz
:  }

: Are we assured of a meaningful answer if the object is not on the
: heap? If not, the facility is useless.

(-: <enter parody mode>
(-: Consider a built-in language feature "delete" that returns storage to
(-: the free store so that it can be allocated again:
(-:
(-:   T1 foo(T2* p) // some function
(-:   {
(-:    ... do something with p
(-:    delete p;
(-:   }
(-:
(-: Are we assured that the future memory management actions will work
(-: correctly?  If not, this "delete" command is useless.
(-:  <exit parody mode>

The rest of the argument is based on the same premise.  To propose a
standard that a new language feature must pass, when that standard is
one not met by basic features already in the language, is an
inappropriate debate tactic.

Unfortunately, I see this tactic used often by defenders of the
language to shoot down ideas from outsiders.

--
Doug Moore
Research Scientist/Lecturer
Computer Science/Computational and Applied Math
(dougm@rice.edu)
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: sriram@allegra.tempo.att.com (M. S. Sriram)
Date: 1996/04/26
Raw View
In article <4ln2rj$6pf@engnews1.Eng.Sun.COM>,
Steve Clamage <clamage@Eng.Sun.COM> wrote:
>dougm@rice.edu (Doug Moore) writes:
>
>>However, another number that is stored for all arrays is the size of
>>the space allocated for the array.  The memory manager must have that
>>information.  As a potential implementor of an Array class, I would
>>like to know, when I ask for an array of size 27, how much space is
>>actually avaiable in the array.
>
>But that information is not available for static or auto objects.
>Even a member function of a class cannot in general know whether
>the object is on the heap or not.

 Is the information necessarily available, even on the heap? If the
delete[] function is a no-op, for instance, new[] could just maintain a
pointer past the last allocated block, with no in-block housekeeping.

 When new[] is overridden, of course, the same sort of implementation
is possible. Maybe for types allocated very infrequently, or long-lived
objects?

[Some lines deleted]
>--
>Steve Clamage, stephen.clamage@eng.sun.com


- Sriram


[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Max TenEyck Woodbury <mtew@cds.duke.edu>
Date: 1996/04/22
Raw View
Steve Clamage wrote:
>
> In article fsf@yorick.cygnus.com, jason@cygnus.com (Jason Merrill) writes:
> >
> >> Igor Boukanov <Igor.Boukanov@fi.uib.no> writes:
> >>
> >> Why do not require that every C++ implementation should provide function
> >> that will return for the pointer obtained from new[] the number of
> >> allocated elements, i.e. something like:
> >>
> >> template<class T> size_t array_allocation_size(T* p);
> >>
> >> So for 'int* p = new int[3];' 'array_allocation_size(p)' will return 3.
> >>
> >> Such function will be very easy to implement because in the case of
> >> delete[] compiler use something like this.
> >
> >Not necessarily.  For instance, g++ only stores the number of elements if
> >
> >1) The element type has a destructor, or
> >2) The element type has an operator delete that takes the size_t argument.
>
> Jason's answer mentions the overhead it would impose on all users whether
> they want the feature or not.
>
> I'd also like to point out that if you need to query an array about its
> size, you probably should not be using a C-style array, but an array
> class instead.
>
> Finally, the proposal mentions only arrays on the heap. Is it the case that
> you care about the size only of arrays allocated with operator new[],
> and not static arrays? What about:
>         extern T myarray[]; // how big is it?
>
> If you use an array class, you can get the functionality you want, and
> don't necessarily have to pay for functionality you don't want. If you
> use the standard vector class, you don't even have to write any code.
> ---
> Steve Clamage, stephen.clamage@eng.sun.com

The purpose of such a function could be to simplify the implementation of
an array class.  The information is available in one form or another to the
delete operator if needed.  Making the same information available to the
class designer in a consistant form would reduce execution overhead, not
increase it.  It would require compiler support of some form, just as the
delete operator requires compiler support.

The proposal dealt specifically with dynamic allocation.  Dragging in
static allocation changes the proposal.  There are ocasions when it is
difficult, if not impossible, to distinguish between static and dynamic
allocation.  Those dificulties already have consequences in the language,
specifically in defining the behavior of the delete operator and the
free() function, so the proposal will not introduce more than minor
variations on existing problems.  Therefore the arguments about static
allocations are mainly irrelavant.

It might be easier if a more primative function were available.  In place
of returning the number of elements in the array, return the allocated size
in the same units returned by sizeof().  Call the function something like
allocsize() and define
     array_allocation_size(T* p) = allocsize(p)/sizeof(p[0]);

I would have used such a function or operator in the string class I
designed, had it been available, to reduce the overhead associated with
each string.  Instead, I stored the information at allocation time.  If I
ever run into a situation where the string overhead is unacceptable, adding
a function that provided this information, in spite of the fact that it
would be VERY implementation dependent, is on the top of my list of
'improvements'.
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: clamage@Eng.sun.com (Steve Clamage)
Date: 1996/04/18
Raw View
In article fsf@yorick.cygnus.com, jason@cygnus.com (Jason Merrill) writes:
>>>>>> Igor Boukanov <Igor.Boukanov@fi.uib.no> writes:
>
>> Why do not require that every C++ implementation should provide function
>> that will return for the pointer obtained from new[] the number of
>> allocated elements, i.e. something like:
>
>> template<class T> size_t array_allocation_size(T* p);
>
>> So for 'int* p = new int[3];' 'array_allocation_size(p)' will return 3.
>
>> Such function will be very easy to implement because in the case of
>> delete[] compiler use something like this.
>
>Not necessarily.  For instance, g++ only stores the number of elements if
>
>1) The element type has a destructor, or
>2) The element type has an operator delete that takes the size_t argument.

Jason's answer mentions the overhead it would impose on all users whether
they want the feature or not.

I'd also like to point out that if you need to query an array about its
size, you probably should not be using a C-style array, but an array
class instead.

Finally, the proposal mentions only arrays on the heap. Is it the case that
you care about the size only of arrays allocated with operator new[],
and not static arrays? What about:
 extern T myarray[]; // how big is it?

If you use an array class, you can get the functionality you want, and
don't necessarily have to pay for functionality you don't want. If you
use the standard vector class, you don't even have to write any code.
---
Steve Clamage, stephen.clamage@eng.sun.com




[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Igor Boukanov <Igor.Boukanov@fi.uib.no>
Date: 1996/04/16
Raw View
    Why do not require that every C++ implementation should provide function
that will return for the pointer obtained from new[] the number of
allocated elements, i.e. something like:

template<class T> size_t array_allocation_size(T* p);

So for 'int* p = new int[3];' 'array_allocation_size(p)' will return 3.

Such function will be very easy to implement because in the case of
delete[] compiler use something like this. So why do not make it available
for programmer?

In this case it will be possible to emulate placement delete for arrays, i.e.
one can write:

template<class T> void array_placement_delete(T* p) {
   size_t i = array_allocation_size(p);
   try { //attempt to support throw in destructors
      while (i > 0) {
         --i;
         p[i].T::~T();
      }
   }
   catch(...) {
      try {
         while(i > 0) {
            --i;
            p[i].T::~T();
         }
      catch(...) {
         terminate();
      }
      throw();
   }
}

and array size doesn't need to be passed to array_placement_delete like in
the ordinary delete[] case...

So what do you think?

--
Regards, Igor Boukanov.
igor.boukanov@fi.uib.no
http://www.fi.uib.no/~boukanov/
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: jason@cygnus.com (Jason Merrill)
Date: 1996/04/17
Raw View
>>>>> Igor Boukanov <Igor.Boukanov@fi.uib.no> writes:

> Why do not require that every C++ implementation should provide function
> that will return for the pointer obtained from new[] the number of
> allocated elements, i.e. something like:

> template<class T> size_t array_allocation_size(T* p);

> So for 'int* p = new int[3];' 'array_allocation_size(p)' will return 3.

> Such function will be very easy to implement because in the case of
> delete[] compiler use something like this.

Not necessarily.  For instance, g++ only stores the number of elements if

1) The element type has a destructor, or
2) The element type has an operator delete that takes the size_t argument.

Jason
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]