Topic: operator new[](size_t, void*) can be more usefull


Author: boukanov@hadron.fi.uib.no (Igor Boukanov)
Date: 1997/02/28
Raw View
It was pointed out a long time ago in this group that current wording
in 5.3.4.12, 1997 C++ Public Review Draft,
<i>
  --new T[5] results in a call of operator new[](sizeof(T)*5+x), and

  --new(2,f) T[5] results in a call of operator new[](sizeof(T)*5+y,2,f).

  Here, x and y are non-negative, implementation-defined  values  repre-
  senting  array  allocation  overhead.  Their value might vary from one
  invocation of new to another.  ]
</i>
does not  permit to use placement operator new[] in any strictly portable
way because it is just impossible to deduce a necessary size for array
before the call to new.

But I do not think that there is any useful implementation of C++ that
violates the following change in this paragraph:
<i>
  --new T[5] results in a call of operator new[](sizeof(T)*5+x), and
                                                            ^^^
  --new(2,f) T[5] results in a call of operator new[](sizeof(T)*5+x,2,f).
                                                                 ^^^
  Here, x is non-negative, implementation-defined value  repre-
  senting  array  allocation  overhead. This value should be
  the same for any invocation of new with the same type and size.
</i>

This will permit the following usage for new[], although I am not sure
that the code is free an from undefined behavior,

inline void* operator new[](size_t size, size& retSize) throw() {
  retSize = size;
  return NULL;
}

template<typename T> inline size_t storageSizeForArray(size_t count){
  size_t size;
  new (size) T[count];
  return size;
}

or probably in more free of undefined behavior way

inline void* operator new[](size_t size, size& retSize) throw(bad_alloc) {
  retSize = size;
  throw (bad_alloc());
}

template<typename T> inline size_t storageSizeForArray(size_t count){
  size_t size;
  try { new (size) T[count];} catch (...) {}
  return size;
}

void * memory = operator new[](storageSizeForArray<int>(10));
int * intArray = new (memory) int[10];
operator delete[](intArary);

Actually the possibility to write portable storage allocation
implementation will be also significantly improved by having
the function that can be used to align properly a pointer
returned by new with possible declaration,

void* make_alignment_for(void* p, size_t max_size, int object_size);

It should return aligned pointer for storage pointed by p with size max_size
that can be used for placement of any object with size object_size or null
if it is impossible to do the alignment for any reason.

The code with make_alignment_for:

char buffer[100];
void* operator new(size_t size) throw (bad_alloc) {
  void* p = make_alignment_for(buffer, sizeof(buffer), size);
  if (p == NULL) throw (bad_alloc());
  return p;
}


A possible implementation can be when alignment is unnecessary

void* make_alignment_for(void* p, size_t max_size, int object_size){
  if (object_size > max_size) return NULL;
  return p;
}

or to align everything on dword boundary:

void* make_alignment_for(void* p, size_t max_size, int object_size){
  int i = reinterpret_cast<int>(p);
  if (object_size >  max_size - i % 4) return NULL;
  return reinterpret_cast<void*>((i + 3) / 4 * 4);
}

What do you think about this?

--
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 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                             ]