Re: newbie: ar[1] at end of POD
andrew_nuss@yahoo.com wrote:
I am creating pools of small integer arrays. There are
individual allocs from the pool, but no frees to the pool, and
one free for the whole pool. The pool creates chunks of 10000
elem arrays. I subdivide the chunk into Snippet as follows:
class Snippet {
friend class SnippetPool;
int ar[1]; // first element is length
// enough room in Snippet object to hold more
elems
// this is the ONLY data member of POD
public:
int length () const
{
return ar[0];
}
int& operator [] (int i)
{
return ar[i+1]; // bounds check omitted
}
Note that this is undefined behavior unless i is -1. Both in C
and in C++.
};
My question is if I have a large chunk of int*, how do I
create Snippets of length N from these chunks? Want it to
work on all platforms!
I'm not sure I understand. An int* is not an int, and if you
have a large chunk of int*, you have int*, and not Snippet.
For example,
class SnippetPool {
// assume that we have one chunk big enough to
// hold all snippets, and destructor throws away chunk
int* buffptr;
int buffcnt;
Snippet* Alloc (int len)
{
len++;
if (len < 1 || len > buffcnt)
throw MyException();
void* p = buffptr;
buffptr += len;
// does the following make assumptions about the C++
// implementation of POD?
Definitly. (Note too that Snippet is NOT a POD.)
What's better?
Maintaining unsigned char*, and adding the actual size of a
Snippet.
Snippet* s = static_cast<Snippet*>(p);
// set the logical length for caller
// but leave rest of array as garbage
s->ar[0] = len-1;
return s;
}
};
It looks to me that first, you are trying to use the dirty
struct hack, which is forbidden in both C and C++. C has since
added VLA, in order to support something similar; C++ hasn't.
It's possible to do something similar, with:
struct Snippet
{
int length ;
int* buffer()
{
return reinterpret_cast< int* >( this + 1 ) ;
}
} ;
As the reinterpret_cast suggests, it is a bit playing with fire,
and you have to be very careful about alignment issues in
particular. (At least at one point in time, g++ did something
similar in its implementation of std::basic_string. And
std::basic_string<double> was a recepe for instant core dump on
my machine.)
Second, if you're managing memory, unless all elements are
really the same type (which isn't the case here), you should use
unsigned char* to manage it, calculating each time how many
bytes you need. (Here too, you need to pay attention to
alignment issues.)
--
James Kanze GABI Software
Conseils en informatique orient?e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S?mard, 78210 St.-Cyr-l'?cole, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]