2011-02-16

Alignment of double values on ARM architectures

Consider the following code:

class C {
...
uint8_t *data;
size_t size;
...

void writeDouble(double v)
{
    ...
    reinterpret_cast<double*>(this->data)[this->size] = v;
    this->size += sizeof(double);
    ...
}

};

Looks harmless enough, doesn't it? But here is the problem: It's not necessarily portable or well behaving code. After debugging for about three hours, I found out something interesting. Namely that on ARM platforms, such as the iPhone, double values on the stack need to be stored at 8 byte aligned memory addresses. This was some existing code I was using, so it took me a while to get to this function and to its problem. Single precision float values have no such restriction, by the way. There are two workarounds in the above case. 1) Write a small for-loop that casts the double value to a uint8_t * and copy the double value byte-wise, or 2) use malloc to copy the value. I did the for-loop, since I thought that maybe the malloc call has too much overhead. I guess you could also cast the double to a uint32_t * pointing to two 32 bit words. Anyway, take care when doing such drastic casts. Some platforms might want alignment for some datatypes!

No comments:

Post a Comment