考虑以下Objective-C ++ iPhone应用程序(TestMemAppDelegate.mm)。它与iPhone上的EXC_BAD_ACCESS崩溃(带有iOS 4.0的3GS)。它在模拟器中工作正常。它显然是一个内存对齐的东西,因为如果“DataA”结构以8字节边框开始,它在iPhone上工作正常。
任何人都可以解释原因吗?这是ARM架构的一部分吗? ARM编译器?
@implementation TestMemAppDelegate
typedef struct DataA
{
float x;
unsigned char y;
};
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
char* mem1 = (char*)malloc(4096);
DataA* ptrA = (DataA*)(mem1 + 1); // Here we shift the alignment
ptrA->x = 10.0f;
printf("A: %.2f\n", ptrA->x); // Here it crashes
// Add the view controller's view to the window and display.
[window addSubview:viewController.view];
[window makeKeyAndVisible];
return YES;
}
@end
答案 0 :(得分:6)
是的,这是一个对齐问题。浮点需要4字节对齐。 Intel x86 CPU允许错误对齐访问(但性能下降)。在ARM上,它是不允许的,并生成您看到的错误。
答案 1 :(得分:0)
浮点数通常必须至少为4字节对齐。
答案 2 :(得分:0)
我认为你会发现它违反了C(可能是C99)标准。 malloc()保证返回适当对齐的内存,因此您可以执行类似
的操作struct DataA * foo = (struct DataA *)malloc(sizeof(struct DataA));
foo->x = 10;
但是有对齐要求,因此无法保证您可以随意修改指针并使其仍然有效。
也就是说,OS可以通过捕获异常并手动执行内存访问来允许未对齐的内存访问。在PowerPC上,CPU处理未对齐的整数访问,但要求操作系统处理未对齐的浮点访问。
最后,可能设法使用GCC扩展程序__attribute__((packed))
来使其工作:
struct foo {
...
} __attribute__((packed));
这有两个影响:
这可能意味着GCC会生成执行未对齐负载所需的代码。但是你为什么要这样做?