下面的代码在 GCC 4.2 上运行得很好,但在 LLVM GCC 4.2 中因 EXC_BAD_ACCESS 而失败
- (double_t)readDouble {
double_t *dt = (double_t *)(buffer+offset);
double_t ret = *dt; // Program received signal: EXC_BAD_ACCESS
offset += 8;
return ret;
}
我就是这么分配的
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);
偏移量和缓冲区就像
@interface PRDataSet : NSObject {
NSMutableArray *tables;
NSMutableDictionary *tablesByName;
NSMutableDictionary *tablesById;
@private
NSURLConnection *conn;
int offset;
char *buffer;
}
是的,偏移量在范围内。 在使用缓冲区之前我不会释放它。
有什么想法吗?
这可能是对齐问题。 ARM 处理器(以及许多其他处理器)对数据对齐有限制,例如它们只能从 4 或 8 倍数的地址读取和写入浮点数。
从代码中分配缓冲区的方式来看,它可能未正确分配,或者您的
double_t
数据元素在缓冲区内未对齐。
为了避免出现此问题,您应该尝试首先将数据复制到对齐的缓冲区中,然后从那里读取数据。
LLVM 只是不直接读取浮点数。
解决方案如下:
- (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;
}