2010-08-09 4 views
2

Considérez l'application iPhone Objective-C++ suivante (TestMemAppDelegate.mm). Il se bloque avec un EXC_BAD_ACCESS sur l'iPhone (3GS avec iOS 4.0). Cela fonctionne très bien dans le simulateur. Il s'agit clairement d'un problème d'alignement de la mémoire, car il fonctionne correctement sur l'iPhone si la structure "DataA" démarre sur une bordure de 8 octets.Un accès mémoire non aligné sur 8 octets entraîne une violation de l'accès mémoire sur l'iPhone 3GS avec iOS 4.0

Quelqu'un peut-il expliquer la cause? Est-ce quelque chose avec l'architecture ARM? Compilateur 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 

Répondre

6

Oui, c'est un problème d'alignement. Un flotteur doit être aligné sur 4 octets. Un processeur Intel x86 permet un accès mal aligné (mais avec une pénalité de performance). Sur ARM, il n'est pas autorisé et génère l'erreur que vous voyez.

+0

Merci. Sur la base de votre réponse, je l'ai trouvée dans la documentation: http://www.keil.com/support/man/docs/ca/ca_ap_byte_alignment.htm –

0

Le flottant doit généralement être aligné sur au moins 4 octets.

0

Je pense que vous trouverez que c'est une violation de la norme C (et vraisemblablement C99). malloc() garantit à retourner la mémoire convenablement alignés, de sorte que vous pouvez faire quelque chose comme

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

Il y a des exigences d'alignement, cependant, il est donc pas garanti que vous pouvez modifier arbitrairement le pointeur et l'ont encore du travail. Cela dit, le système d'exploitation peut permettre un accès mémoire mal aligné en attrapant l'exception et en effectuant l'accès à la mémoire manuellement. Sur PowerPC, le processeur gère les accès entiers désalignés, mais s'attend à ce que le système d'exploitation gère les accès en virgule flottante mal alignés.

Enfin, vous pourriez réussi à le faire fonctionner en utilisant l'extension GCC __attribute__((packed)):

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

Cela a deux effets:

  • variables dans le struct ont alignement 1 (ce qui peut modifier la disposition de la mémoire de votre structure)
  • La structure a l'alignement 1 (ie le compilateur ne l'aligne plus lorsque vous le collez dans une autre structure, par exemple ple)

Cela peut signifier que GCC génère le code nécessaire pour effectuer la charge désalignée. Mais pourquoi voudriez-vous faire cela?

Questions connexes