2010-08-09 80 views
2

请考虑以下Objective-C++ iPhone应用程序(TestMemAppDelegate.mm)。它在iPhone上使用EXC_BAD_ACCESS(iOS 4.0的3GS)崩溃。它在模拟器中工作正常。这显然是一个内存对齐的事情,因为如果“DataA”结构在8字节边界上启动,它可以在iPhone上正常工作。非8字节对齐的内存访问会导致iOS 4.0的iPhone 3GS上的内存访问冲突

任何人都可以解释原因吗?这是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 

回答

6

是的,这是一个对齐问题。浮点数需要4字节对齐。 Intel x86 CPU允许错误对齐访问(但性能损失)。在ARM上,它是不允许的,并产生你看到的错误。

+0

谢谢。基于你的回答,我在文档中找到了它:http://www.keil.com/support/man/docs/ca/ca_ap_byte_alignment.htm – 2010-08-09 13:44:49

0

浮点数通常必须至少为4字节对齐。

0

我想你会发现它违反了C(和C99)标准。的malloc()保证返回适当对齐的存储空间,这样你就可以这样做

struct DataA * foo = (struct DataA *)malloc(sizeof(struct DataA)); 
foo->x = 10; 

有对齐要求,虽然如此,它不能保证你可以任意修改指针,并将它仍然可以工作。

也就是说,操作系统可以通过捕获异常并手动执行内存访问来允许未对齐的内存访问。在PowerPC上,CPU处理未对齐的整数访问,但期望操作系统处理未对齐的浮点访问。

最后,你可能设法得到它使用GCC扩展__attribute__((packed))工作:

struct foo { 
    ... 
} __attribute__((packed)); 

这有两个方面的影响:在结构

  • 的变量必须对齐1(这可能改变你的结构的内存布局)
  • 该结构具有对齐1(即编译器不再将它对齐时,你把它粘在另一个结构,考试ple)

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