非8字节对齐的内存访问会导致iPhone 3GS与iOS 4.0的内存访问冲突

时间:2010-08-09 10:29:23

标签: iphone memory malloc arm objective-c++

考虑以下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

3 个答案:

答案 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));

这有两个影响:

  • 结构中的变量具有对齐1(这可能会更改结构的内存布局)
  • 结构具有对齐1(例如,当您将其粘贴到另一个结构中时,编译器不再对齐它),

这可能意味着GCC会生成执行未对齐负载所需的代码。但是你为什么要这样做?