简体   繁体   English

Objective-C-复制exit(0)并修复EXC_BAD_ACCESS

[英]Objective-C - Replicating exit(0) and fixing EXC_BAD_ACCESS

Having some seriously frustrating issues with my latest app!! 我的最新应用存在一些严重令人沮丧的问题!!

I'm using OpenGLES 1 to draw models to the screen that are constantly updating, then you can take a screenshot and share however you like, after that you can return to the app start screen and start again. 我正在使用OpenGLES 1在不断更新的屏幕上绘制模型,然后您可以截取屏幕截图并按自己的喜好进行共享,之后您可以返回到应用程序启动屏幕并重新启动。

All seems to work fine the first time the app runs through, no crashes. 第一次运行该应用程序时,一切似乎都正常,没有崩溃。 But if you run through it once then try to go through again, as soon as the OpenGLES drawing view has to start drawing the elements, it throws up an EXC_BAD_ACCESS error on my glDrawElements line. 但是,如果您运行它一次,然后尝试再次尝试,一旦OpenGLES绘图视图必须开始绘制元素,它EXC_BAD_ACCESS在我的glDrawElements行上引发EXC_BAD_ACCESS错误。

I given up on trying to fix this error for now, I've had no luck in the last 2 weeks!! 我暂时放弃尝试修复此错误,最近2星期我没有运气!!

I have set the property in my plist so that the app doesn't run in the background, and whenever I run it through once, then exit it and load it up again it will run through again absolutely fine. 我已在我的plist中设置了该属性,以使该应用程序不会在后台运行,并且每当我运行一次该应用程序,然后退出并再次加载它,它将再次正常运行。

So what I was wondering is if I could somehow emulate the functionality of the exit(0) feature, but without actually exiting from the app? 所以我想知道的是,我是否可以以某种方式模拟exit(0)功能的功能,而无需实际退出应用程序?

So in essence, each time the user navigates from the sharing page back to the home page, the app would run the exit code, leaving the app to run from scratch again. 因此,从本质上讲,每次用户从共享页面导航回到主页时,该应用程序都会运行exit代码,而使应用程序再次从头开始运行。

This would, in my head at least, not be a great way at all of dealing with the situation, but I need results quick and this seems like a good way out for now until I can get to the bottom of the actual error. 至少在我看来,这根本不是解决这种情况的好方法,但是我需要快速获得结果,这似乎是一个不错的出路,直到我能找到实际错误的最低点为止。

Thanks, 谢谢,

Matt 马特

EDIT 1: I'm not looking to put the app on the store with this fix in place, it is just a temporary thing. 编辑1:我不希望将应用程序与此修复程序一起放在商店中,这只是暂时的事情。

EDIT 2: Posted code containing my draw functionality, taken and adapted from Bill Dudney's WaveFront .obj loader 编辑2:包含我的绘图功能的已发布代码,取自并改编自Bill Dudney的WaveFront .obj loader

for(WaveFrontOBJGroup *group in scene.groups)
{
    NSString *matPath = [NSString stringWithFormat:@"%@%@.mtl", materialName, modelPart];
    NSArray *materialArray = [WaveFrontOBJMaterial materialsFromLibraryFile:matPath];
    WaveFrontOBJMaterial *mat = [materialArray objectAtIndex:0];

    if(group.smoothing)
        glShadeModel(GL_SMOOTH);
    else
        glShadeModel(GL_FLAT);

    // load (if necessary) and bind the vertices
    GLuint verticesName = [group verticesName:GL_STATIC_DRAW];
    glBindBuffer(GL_ARRAY_BUFFER, verticesName);
    glVertexPointer(3, GL_FLOAT, 0, 0);

    // load (if necessary) and bind the normals
    GLuint normalsName = [group normalsName:GL_STATIC_DRAW];
    glBindBuffer(GL_ARRAY_BUFFER, normalsName);
    glNormalPointer(GL_FLOAT, 0, 0);

    ColorRGBA color = mat.ambientColor;
    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (GLfloat *)&color);
    color = mat.diffuseColor;
    if(alpha)
        glColor4f(color.red, color.green, color.blue, mat.disolve);
    else
        glColor4f(color.red, color.green, color.blue, color.alpha);
    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (GLfloat *)&color);
    color = mat.specularColor;
    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (GLfloat *)&color);
    glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, mat.shine);

    // load (if necessary) and bind the texture
    if(group.textureCoordinatesIndexData.length > 0)
    {
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        GLuint textureCoordsName = [group textureCoordinatesName:GL_STATIC_DRAW];
        glEnable(GL_TEXTURE_2D);
        glBindBuffer(GL_ARRAY_BUFFER, textureCoordsName);
        glTexCoordPointer([group texCoordSize], GL_FLOAT, 0, 0);
        GLuint texId = [mat.diffuseTexture textureName];
        glBindTexture(GL_TEXTURE_2D, texId);
    }

    GLuint indexesName = [group indexesName:GL_STATIC_DRAW];
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexesName);

    glDrawElements(GL_TRIANGLES, group.indexCount, GL_UNSIGNED_SHORT, NULL);
    //^^This line above is where I get the "EXC_BAD_ACCESS" message

    if(group.textureCoordinatesIndexData.length > 0)
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}

I've checked group.indexCount through breakpoints and NSLog's and it is not null, it is exactly the same as when it runs through the first time which works fine. 我已经通过断点和NSLog检查了group.indexCount ,并且它不为null,它与第一次运行时完全一样,可以正常工作。

I realise it won't necessarily be on that line, I've heard other talk about it being due to variables not being initialised as pointers - * - or NSStrings not having matching identifiers and values (@"%@ sometext %@", variable); 我意识到它不一定会在那一行上,我听说过其他有关它的讨论,这是由于变量没有初始化为指针- * -或NSStrings没有匹配的标识符和值(@"%@ sometext %@", variable); but I don't see any of those in my code, of course I could easily be missing one. 但是我在代码中看不到任何一个,当然我很容易会错过一个。

Remember two things: 记住两件事:

1) You have a method -(void)viewWillAppear:(BOOL)animated in your home ViewController. 1)您在家庭ViewController中设置了-(void)viewWillAppear:(BOOL)animated This will call always (!) when user return to this screen (not like viewDidLoad). 当用户返回此屏幕时,它将始终调用(!)(与viewDidLoad不同)。

2) If you even do this like you described you probably didn't get to the AppStore! 2)如果您甚至按照您的描述进行操作,那么您可能没有进入AppStore!

I'm not sure why your application won't compile on the simulator, but you should try to link your libraries appropriately so that you can get that up and running - nothing is better for bad access errors than zombies. 我不确定为什么您的应用程序无法在模拟器上编译,但是您应该尝试适当地链接您的库,以便您可以启动它并运行它-没有比僵尸更好的访问错误了。

If you know your error is from calling glDrawElements then you should look into what's being passed to it. 如果您知道错误是由于调用glDrawElements那么您应该查看传递给它的内容。 This link might be able to help you. 此链接可能会为您提供帮助。

The reason you can't get the "functionality" of exiting your app while still in the app is because it's not a function of the application - it's the OS throwing away everything associated with the application and then reloading it. 无法获得仍在应用程序中退出应用程序的“功能”的原因是因为它不是应用程序的功能-是操作系统丢弃了与该应用程序关联的所有内容,然后重新加载它。 By definition you won't be able to do this without actually shutting down. 根据定义,如果没有真正关闭,您将无法执行此操作。

However, if your problem is fixed by this, then it is likely that there's something in your setup that needs to be redone (initializations, declarations, etc). 但是,如果这样解决了您的问题,则可能是您的设置中有一些需要重做的东西(初始化,声明等)。 Check to see what's getting set to nil or thrown away and then set it back up. 检查一下将什么设置nil或丢弃,然后将其备份。

Without looking at your code I can't say this with any certainty, but you may be able to write a method that overwrites/reinitializes all of your current variables. 如果不看代码,就无法确定地说什么,但是您可以编写覆盖/重新初始化当前所有变量的方法。 This would probably replicate the part of exiting the application that you need. 这可能会复制退出所需应用程序的部分。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM