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
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
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
@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. –