2011-04-13 1 views
0

Celui-ci me rend fou. J'ai récemment introduit du code qui stocke des données d'image à partir d'une vue OpenGL dans un objet NSData, et stocke cela dans les données de base. En récupérant cela, et en essayant de ramener ces données de pixel à une texture, je reçois une erreur EXC_BAD_ACCESS.Frustrant EXC_BAD_ACCESS (NSData/OpenGL liés?) Sur l'appareil - fonctionne bien sur le simulateur

Voici le code qui provoque le bug:

- (void)drawDrawingFromData:(NSData *)data { 

    if (data != nil) { 
     [renderer prepareRetainedBuffer]; 

     /* Prepare data in raw bytes */ 
     NSInteger width = self.bounds.size.width, height = self.bounds.size.height; 
     NSUInteger dataLength = width * height * 4; 
     unsigned char pixelData[dataLength]; 
     [data getBytes:pixelData length:dataLength];    // <---- EXC_BAD_ACCESS here. 

     /* Create a texture to render using pixel data */ 
     GLuint imageTexture; 
     glGenTextures(1, &imageTexture);       // <---- EXC_BAD_ACCESS occurs here if the [data getBytes:length:] line is commented out. 
     glBindTexture(GL_TEXTURE_2D, imageTexture); 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixelData); 


     glEnableClientState(GL_VERTEX_ARRAY); 
     glEnableClientState(GL_TEXTURE_COORD_ARRAY); 

     // Destination coords. 
     GLfloat retainedVertices[] = { 
      0.0, 0.0, 
      width, 0.0, 
      0.0, height, 
      width, height, 
     }; 

     // Source coords. 
     GLfloat retainedTexCoords[] = { 
      0.0, 1.0, 
      1.0, 1.0, 
      0.0, 0.0, 
      1.0, 0.0 
     }; 

     glColor4f(1.0, 1.0, 1.0, 1.0); 
     glBindTexture(GL_TEXTURE_2D, imageTexture); 
     glVertexPointer(2, GL_FLOAT, 0, retainedVertices); 
     glTexCoordPointer(2, GL_FLOAT, 0, retainedTexCoords); 
     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 

     glDisableClientState(GL_VERTEX_ARRAY); 
     glDisableClientState(GL_TEXTURE_COORD_ARRAY); 


     [renderer renderSceneWithScratch:NO]; 
     [renderer presentScene]; 
    } 
} 

Ce qui rend ce extrêmement frustrant pour moi est que tout fonctionne parfaitement bien sur le simulateur. Aussi, je suis assez confiant que ce code exact a effectivement fonctionné sur l'appareil quelques heures plus tôt ... peut-être que je deviens fou!

J'ai essayé ce qui suit sans succès:

  • nous avons vérifié que le tableau est pixelData assez grand pour stocker tous les octets de l'objet NSData.
  • Redémarré le périphérique, redémarré Xcode (version 4 par ailleurs), fait une construction propre , effacé le modèle de données de base et reconstruit.
  • Garantit que l'objet NSData est correctement conservé lorsqu'il est appelé.
  • Les lignes ont graduellement commenté le code
    . Pour chaque ligne je commente,
    l'erreur EXC_BAD_ACCESS déplace
    plus bas. Est-ce que cela signifie que l'erreur pourrait être le résultat de
    quelque chose qui revient d'un autre thread
    ?

Celui-ci me déconcerte vraiment. Le plus ennuyeux est pourquoi tout fonctionne bien dans le simulateur. J'apprécierais grandement toute aide sur celui-ci!

EDIT

Voici la trace de l'erreur:

#0 0x36cc6c92 in objc_msgSend() 
#1 0x0001e71c in -[EAGLView drawDrawingFromData:] (self=0x14dbf0, _cmd=0x4e16f, data=0x13dbd0) at /Users/Stu/Documents/... 
#2 0x0001df30 in -[EAGLView layoutSubviews] (self=0x14dbf0, _cmd=0x329644ac) at /Users/Stu/Documents/... 
#3 0x326675fa in -[UIView(CALayerDelegate) layoutSublayersOfLayer:]() 
#4 0x35ee2f02 in -[NSObject(NSObject) performSelector:withObject:]() 
#5 0x333e2bb4 in -[CALayer layoutSublayers]() 
#6 0x333e296c in CALayerLayoutIfNeeded() 
#7 0x333e81c4 in CA::Context::commit_transaction() 
#8 0x333e7fd6 in CA::Transaction::commit() 
#9 0x333e1054 in CA::Transaction::observer_callback() 
#10 0x35f4ca34 in __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__() 
#11 0x35f4e464 in __CFRunLoopDoObservers() 
#12 0x35f4f75a in __CFRunLoopRun() 
#13 0x35edfec2 in CFRunLoopRunSpecific() 
#14 0x35edfdca in CFRunLoopRunInMode() 
#15 0x3253c41e in GSEventRunModal() 
#16 0x3253c4ca in GSEventRun() 
#17 0x32690d68 in -[UIApplication _run]() 
#18 0x3268e806 in UIApplicationMain() 
#19 0x000023a0 in main (argc=1, argv=0x2fdff540) at /Users/Stu/Documents/... 

Merci

Répondre

1

Vous allouez pixelData sur la pile. Il est probable que vous débordiez la pile de l'appareil, qui est probablement plus petite que ce que permet le simulateur. Je suggère de l'allouer sur le tas en utilisant new à la place.

+0

Je pensais que 'new' est une fonctionnalité de C++? Comment puis-je l'utiliser pour allouer sur le tas dans une application obj-c? Désolé pour mon ignorance ... – Stuart

+0

Ah - pense que j'ai répondu à ma propre question là-bas. Je suppose que c'est l'équivalent de 'malloc' en C. J'ai utilisé le code suivant pour allouer les données maintenant:' unsigned char * pixelData = (caractère non signé *) malloc (dataLength * sizeof (unsigned char)) ' , et il semble avoir résolu le problème, merci beaucoup pour la perspicacité. – Stuart

+0

@StuDev: Notez que XCode vous permet de mélanger C++ et Obj-C dans les fichiers Obj. C++ '.mm' si vous avez besoin des fonctionnalités. De plus, n'oubliez pas de 'free (pixelData)' à la fin de la fonction, il n'est plus nécessaire. –

Questions connexes