0

Below code runs just fine on GCC 4.2 but fails with EXC_BAD_ACCESS in LLVM GCC 4.2

- (double_t)readDouble  {
    double_t *dt = (double_t *)(buffer+offset);
    double_t ret = *dt; // Program received signal: EXC_BAD_ACCESS
    offset += 8;
    return ret;
}

That's how I allocate

int dataLength = [data length];
buffer = malloc(dataLength + 1);
buffer[dataLength] = 0; // null terminate to log
[data getBytes:(void *)buffer length:[data length]];
//NSLog(@"%s", buffer);

Offset and buffer is like

@interface PRDataSet : NSObject {

    NSMutableArray *tables;
    NSMutableDictionary *tablesByName;
    NSMutableDictionary *tablesById;

@private
    NSURLConnection *conn;
    int offset;
    char *buffer;

}

Yes offset is within range. I do not free the buffer before I use it.

Any ideas?

2 Answers2

2

This could be an aligment problem. The ARM processors (and many other processors) have restrictions regarding the data alignment, e.g. they can only read and write floating-point numbers from addresses that are a multiple of 4 or 8.

From the way the buffer is allocated in your code, it might not be allocated properly, or your double_t data elements aren't aligned within the buffer.

In order to avoid the problem, you should try to first copy the data into an aligned buffer and read it from there.

Codo
  • 75,595
  • 17
  • 168
  • 206
  • You are right. It is about floating-point alignment. My buffer is set up from different data types so I could not align the buffer. The solution is reading as integer and then casting to floating-point numbers. I think that's what GCC did. LLVM does not do this correction but I think it should in the future. Developers don't need to know processor restrictions. That's what compilers are for. – Serdar T Kabaoglu May 21 '11 at 13:45
1

LLVM just doesn't read float directly.

Here's the solution:

- (uint32_t)readUInt32  {
    uint32_t ret = *(uint32_t *)(buffer+offset);
    offset += 4;
    return ret;
}

- (uint16_t)readUInt16  {
    uint16_t ret = *(uint16_t *)(buffer+offset);
    offset += 2;
    return ret;
}

- (uint64_t)readUInt64  {
    uint64_t ret = *(uint64_t *)(buffer+offset);
    offset += 8;
    return ret;
}

- (float_t)readSingle  {
    uint32_t t = [self readUInt32];
    float_t ret = *((float_t *)(&t));
    return ret;
}

- (double_t)readDouble  {
    uint64_t t = [self readUInt64];
    double_t ret = *((double_t *)(&t));
    return ret;
}