"Bertel Brander" <bertel@post4.tele.dk> wrote in message
news:42c44000$0$274$edfadb0f@dread11.news.tele.dk...
> Mogens Hansen wrote:
>> "Bertel Brander" <bertel@post4.tele.dk> wrote in message
>> news:42c308be$0$261$edfadb0f@dread11.news.tele.dk...
>>
>> [8<8<8<]
>>
>>>Ja, jeg kan godt gemme information om hvor mange bytes, der skulle
>>>allokeres, men jeg er ikke sikker på at der er nogen entydig
>>>sammenhæng mellem antallet af bytes og antallet af elementer i
>>>array'et.
>>>new[] operatoren kender normalt ikke typen på det der skal allokeres
>>>og kan dermed ikke beregne antallet af elementer.
>>>delete[] får måske en pointer til en afledt class, og så kan den vel
>>>heller ikke beregne antallet.
>>
>>
>> Du kender typen i den template funktion der skal frigive arrayet.
>> Dermed kender du størrelsen på hvert objekt og kan du beregne antal
>> objekter.
>
> Desværre er det ikke så let.
> Jeg lavede et lille test project:
>
> #include <iostream>
> #include <new>
>
> enum Whatever
> {
> Something
> };
>
> class X
> {
> public:
> X() : x(Next++)
> {}
> ~X()
> {}
> int x;
> static int Next;
> };
>
> int X::Next;
>
> void *operator new(size_t aSize)
> {
> return malloc(aSize);
> }
>
> void *operator new[](size_t aSize)
> {
> return malloc(aSize);
> }
>
> void *operator new[] (size_t aSize, Whatever aWhatever)
> {
> std::cout << aSize << std::endl;
> size_t *p = (size_t *)malloc(aSize + sizeof(size_t));
> *p = aSize;
> p += 1;
> std::cout << "New[] returning: " << p << std::endl;
> return p;
> }
>
> template<typename T> void destroy(T *t)
> {
> std::cout << "destroy receiving: " << t << std::endl;
> size_t n = *(size_t *)((char *)t - sizeof(size_t));
> std::cout << n << " " << sizeof(T) << std::endl;
> for(size_t i = 0; i < n/sizeof(T); i++)
> t[i].~T();
> }
>
> int main()
> {
> X *p;
> p = new(Something) X[4];
> destroy(p);
> p = new(Something) X[5];
> destroy(p);
> }
>
> Når jeg kører det kan jeg se at den addresse som new returnerer
> IKKE er den adresse om destroy får.
Det lyder underligt.
Jeg kan ikke hurtigt se hvad der er galt - men det er muligt.
I går skrev jeg noget næsten tilsvarende (det var det udkommenterede kode
der kørte).
#include <new>
#include <iostream>
using namespace std;
class foo
{
public:
foo()
{ cout << "foo::foo(0x" << hex << this << ")" << endl; }
~foo()
{ cout << "foo:
foo(0x" << hex << this << ")" << endl; }
};
enum tag_my_memory_pool
{
MMP
};
void* operator new [] (size_t size, tag_my_memory_pool) throw
(std::bad_alloc)
{
// void* mem = operator new(size + sizeof(size_t));
// size_t* s = reinterpret_cast<size_t*>(mem);
// *s = size;
// return reinterpret_cast<char*>(mem) + sizeof(size_t);
return operator new (size);
}
void operator delete [] (void* mem, tag_my_memory_pool)
{
operator delete (reinterpret_cast<char*>(mem) - sizeof(size_t));
}
template <typename T, typename P>
void delete_array_pool(T* first_obj, P pool)
{
if(!first_obj)
return;
void* mem = first_obj;
size_t* s = reinterpret_cast<size_t*>(reinterpret_cast<char*>(mem) -
sizeof(size_t));
const size_t size = (*s)/*/sizeof(foo)*/;
for(size_t i = 0; size != i; ++i) {
T* t = &first_obj[size-i-1];
t->~T();
}
operator delete [] (first_obj, pool);
}
int main()
{
foo* fp = new (MMP) foo[7];
delete_array_pool (fp, MMP);
}
Der var det samme adresse "operator new []" returnerede som
"delete_array_pool" fik.
Det gik også fint nok med at skrive størrelsen på blokken i "operator new
[]".
MEN, engentligt ikke overraskende, skriver implementeringerne (compilerne)
som jeg prøvede også i området før den adresse som "operator new []"
returner. Og egentligt ikke overraskende skriver den hvormange elementer der
er i arrayet
Således virker den kode der ikke er udkommenteret fint på de 2 compilere jeg
prøvede med - men det er _ikke_ portabelt eller på nogen måde
veldokumenteret at det burde virke.
> Man kunne måske finde addressen, men koden skal helst være
> rimelig portabelt.
>
>> Måske var det en ide at overveje at bruge "std::vector" med en speciel
>> allokator.
>
> Der bruges en del std::vector og std::list, som alle skal bruge en
> speciel allokator, desværre er der en del char/int/whatever *,
> som ikke kan laves om til std::vector.
Ting (char/int/whatever) der ligger i en std::vector kan sagtens overføres
til funktioner der forventer et array af ting.
Men det hjælper måske ikke på dit problem.
Venlig hilsen
Mogens Hansen