Re: understanding strict aliasing
On Nov 20, 5:22 pm, Alberto Griggio <alberto.grig...@gmail.com> wrote:
Ok, let's see if I am understanding you correctly then.
Given what you write above (and after having read also the relevant parts of
the standard again) and your previous example, if I understood everything
correctly, then this should work:
Pool()
{
chunks = new Chunk();
char *start = chunks->mem;
head = new (start) Link();
char *last = &(start[(4-1) * sizeof(Link)]);
for (char *p = start; p < last; p += sizeof(Link)) {
Link *n = new (p + sizeof(Link)) Link();
reinterpret_cast<Link *>(p)->next = n;
}
reinterpret_cast<Link *>(last)->next = 0;
}
void *alloc()
{
Link *p = head;
head = head->next;
return p;
}
void free(void *p)
{
Link *l = new (p) Link();
l->next = head;
head = l;
}
When Pool::free is called, p is a pointer to a memory block that must be
freed, and therefore it will not be accessed from the rest of the program
before a subsequent call to Pool::alloc. Therefore, p is not aliased
anywhere else in the program. Then, I'm starting the life of the POD Link
object by using a placement new. Therefore, it is safe to access l->next in
Pool::free. A similar situtation occurs also in Pool::alloc, since I've used
a placement new in Pool::Pool() for setting up the linked list.
Or am I still wrong?
If you post some complete code, I might be better able to determine
it's correctness. Are you using the same definitions of chunk and
link?
At the very least, you still have alignment problems for a generic
implementation, which is undefined behavior, which could cause it to
crash. It's possible that you could have a data type, say double,
which requires a certain alignment, and that char array member sub-
object may not be correctly aligned to hold a double object.
I'm not actually sure the best way offhand to deal with the alignment
problem. I would probably first find out what the biggest basic data
type is, pointer, double, whatever, on the hardware which I care
about, and just return memory to the user which is aligned on that
alignment so the user can put whatever object he wants into it. (This
is also a requirement for the type of function the C++ standard calls
"an allocation function". I don't remember much offhand.)
Also, I'm not quite sure what you're trying to do with that new code.
I would probably take my code, ensure it's actually bug free, fix the
alignment issues, and use that. Notice how mine has exactly one cast,
the static_cast in free to get the void pointer back to the Link
pointer - whereas your code has many more casts. Casts should be kept
to a minimum in code, and generally casting is a sign of a bad design.
In this case, I would argue that malloc and free are an example of bad
design, a lack of type safety. This is related to how C also lets
void* be cast to any pointer type implicitly in order to make malloc
not excessively annoying to use, and other similar generic data
structures and algorithms. In C++, this mostly isn't needed because of
new and delete, its type safe containers based on templates. With C+
+0x with variadic templates, void* casting hackery will be needed even
less.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]