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 ]