3.4.9 crash on xcode 6.3 on device
Birkemose opened this issue · 31 comments
Adding this line
sprite.effect = [CCEffectBlur effectWithBlurRadius:1];
Causes xcode 6.3 to crash on device, with the following error:
error: memory read failed for 0x0
When checking ex. CCEffectBlur, self is used before it is assigned.
I think we need to review effects again, as stuff like this can cause some really weird behaviour.
@Birkemose, where are you seeing the crash and reference to self before it's assigned? Over the last few months I've done a bunch of effect initialization cleanup to get rid of issues like that but it's quite possible I missed something.
@thayerandrews, it only seems to happen on device, and while it is frequent, it apparently isn't always. When you find a device and it starts to crash, it seems to be pretty consistent though.
I had a quick look at CCEffectBlur, and noticed code is executed before calling super. That might not be the cause, but I think it is dangerous grounds to work on an object, before the super has been properly initialised. It can result in some really really bad bugs.
I haven't had time to look further into it yet. As it isn't all devices, and as the reports I have seen so far, all are 32 bit devices, I guess that is where I would go looking first.
Okay, I'll take a look and see what I can see. Thank you for the additional information.
Yeah, sorry for not being more specific from the beginning.
I actually tried several effects (not all of them), and those I tried (unfortunately I can only remember blur) all crashed, so it might be something several effects have in common.
Thinking about it. The device I experienced this on, was an iPad2. I do not have access to it until tomorrow, but here my 5S and iPad Air are both working, so maybe it actually is an 32 bit issue.
No worries. I'll get it going on my old 4s and see if it breaks for me.
Okay, I am able to reproduce this on my 4s running iOS 8.3. I'm seeing it with CCEffectLighting and I've not checked it with any other effects.
It's not happening at initialization time but actually happens later when tweaking the sprite vertices during effect rendering. The crash occurs when assigning the new CCSpriteVertexes struct to the CCEffectRenderPassInputs and there seems to be a stack corruption element to it since stepping into the property setter yields an invalid stack in Xcode.
Unfortunately, it is not reproducible on the simulator with or without all the various guard malloc options enabled. No huge surprise there but I figured it was worth a try.
I had a brief look at it, and I seem to be able to reproduce it every time on 32 bit devices.
The crash is when assigning verts in line 276 in CCEffectRenderer, and everything - including the return value - looks fine up until the actual assignment, at which it crashes with no debug information. I have never seen this kind of crash with Xcode before, and I am starting to believe it is a compiler bug.
On 29 Apr 2015, at 21:23, thayerandrews notifications@github.com wrote:
Unfortunately, it is not reproducible on the simulator with or without all the various guard malloc options enabled. No huge surprise there but I figured it was worth a try.
—
Reply to this email directly or view it on GitHub #1301 (comment).
Yup. I now have a simplified test case (it doesn't use Cocos2D at all) that reproduces the problem. I'm in the process of beefing it up and I will push it to github and add a link here once it's ready.
At this point I think it's either a compiler bug or a runtime bug. It seems related to calling a method with either a large struct argument or a nested set of structs as we have in the case of CCSpriteVertexes (which contains CCVertex and in turn contains various GLK vector types). My suspicion is that something is going wrong with the stack setup code for this method call which corrupts the stack thus resulting in the crash (and the bad stack that I see when I break in the property setter).
Do you have time to fix this next week, otherwise I can?
On 30 Apr 2015, at 17:07, thayerandrews notifications@github.com wrote:
Yup. I now have a simplified test case (it doesn't use Cocos2D at all) that reproduces the problem. I'm in the process of beefing it up and I will push it to github and add a link here once it's ready.
At this point I think it's either a compiler bug or a runtime bug. It seems related to calling a method with either a large struct argument or a nested set of structs as we have in the case of CCSpriteVertexes (which contains CCVertex and in turn contains various GLK vector types). My suspicion is that something is going wrong with the stack setup code for this method call which corrupts the stack thus resulting in the crash (and the bad stack that I see when I break in the property setter).
—
Reply to this email directly or view it on GitHub #1301 (comment).
Yeah. I think I've found a workaround that will get things working again until a real fix comes along.
Sounds good
On 30 Apr 2015, at 18:24, thayerandrews notifications@github.com wrote:
Yeah. I think I've found a workaround that will get things working again until a real fix comes along.
—
Reply to this email directly or view it on GitHub #1301 (comment).
For what it's worth, here is the simplified test case that I created this morning to recreate this issue. I haven't inspected the generated assembly code but the problem is related to struct size and struct member alignment. I will file a radar with Apple and include this test case.
Bummer. Definitely seems like a compiler bug. I ran your test case on my 64 bit iPad with both Xcode 6.1 and 6.3, no crashes. On my 32 bit iPhone, it works fine with Xcode 6.1, but crashes with Xcode 6.3. Not sure if that's helpful to know.
I should be working on other things... but this sounded like more fun. It was crashing on a read to 0x40000000 for me. Stepping by instruction, it makes it into the setVerts: method just fine.
(lldb) po $r0
<MyTestClass: 0x15d1f730>
(lldb) p (char *)$r1
(char *) $5 = 0x0004e671 "setVerts:"
The function prolog pushes the link register (which was 0x0004efa7), and then does other stuff. At the end of the function, it pops the link register and it has the value 0x40000000! The stack pointer is in the right location, but something is overwriting the pushed value of the link register somewhere in between. Even if I change the method to do nothing, it overwrites the link register's value. Definitely seems like a compiler bug to me.
@thayerandrews I'm curious what your workaround was.
Workaround was posted here
http://forum.cocos2d-spritebuilder.org/t/cceffectbrightness-crashed-on-iphone4s/17124/8 http://forum.cocos2d-spritebuilder.org/t/cceffectbrightness-crashed-on-iphone4s/17124/8
On 01 May 2015, at 00:25, Scott Lembcke notifications@github.com wrote:
Bummer. Definitely seems like a compiler bug. I ran your test case on my 64 bit iPad with both Xcode 6.1 and 6.3, no crashes. On my 32 bit iPhone, it works fine with Xcode 6.1, but crashes with Xcode 6.3. Not sure if that's helpful to know.
I should be working on other things... but this sounded like more fun. It was crashing on a read to 0x40000000 for me. Stepping by instruction, it makes it into the setVerts: method just fine.
<MyTestClass: 0x15d1f730>
(lldb) p (char *)$r1
(char *) $5 = 0x0004e671 "setVerts:"
The function prolog pushes the link register (which is 0x0004efa7), and then does other stuff. At the end of the function, it pops the link register and then it has the value 0x40000000! The stack pointer is in the right location, but something is overwriting the pushed value of the link register somewhere in between. Even if I change the method to do nothing, it overwrites the link register's value. Definitely seems like a compiler bug to me.@thayerandrews https://github.com/thayerandrews I'm curious what your workaround was.
—
Reply to this email directly or view it on GitHub #1301 (comment).
@slembcke Thanks for digging into it a bit too. The knowledge that it works on Xcode 6.1 is definitely helpful.
My plan for a workaround is to just set each vertex value individually since the smaller structs don't have problems. The posted solution of passing a pointer works too. I'm off to dinner but I'll check in the WA in the morning.
Here are some other device tests using @thayerandrews test suite:
All with XCode 6.3.1 (6D1002):
32 bit devices:
- iPhone 4 (MC603B/A) - iOS 7.1.2 (11D257) - Crash error on all 5 versions
- iPad 3 (MC706B/A) - iOS 8.3 (12F69) - Crash error on all 5 versions
- iPad Mini 1 (MD528B/A) - iOS 8.3 (12F69) - Crash error on all 5 versions
- iPhone 5 (MD299B/A) - iOS 8.3 (12F70) - Crash error on all 5 versions
64 bit devices:
- iPad Air 2 (MGKL2B/A) - iOS 8.3 (12F69) - Passed all 5 versions
- iPhone 6+ (MGAJ2B/A) - iOS 8.3 (12F70) - Passed all 5 versions
For another test, I ran the two 64-bit devices with 32-bit code (armv7 architecture build only):
- iPad Air 2 - Crash error on all 5 versions
- iPhone 6+ - Crash on all 5 versions
And the same results when architecture was 'armv7s' only too on the first version (didn't test all 5 for this).
So with everything else it is pretty conclusive that it is the 32 bit compiler ARM output that is broken.
This is terrific. Thanks @richardgroves!
No new information, just adding a link to the new forum post since the Cocos2D domain changed.
Hi there is there any chance someone can get an extract from the workaround posted somewhere more exposed on the forum? Logged in the forum says "Sorry, you don't have access to that topic!" and the newer link post domain change shows the Discourse logo and: "The page you requested doesn't exist or is private.". I understand that the nature of the problem is an issue with the structs copying of value references between methods or simply put assignment of complex struct objects.
I did manage to render my own quick fix but it can probably be refined:
CCSpriteVertexes verts = padVertices(sprite.vertexes, effect.padding, tc1, tc2);
[renderPassInputs setVerts:&verts];
-(CCSpriteVertexes)getVerts {
return verts;
}
-(void)setVerts:(CCSpriteVertexes*)newVerts {
verts.bl = newVerts->bl;
verts.br = newVerts->br;
verts.tr = newVerts->tr;
verts.tl = newVerts->tl;
}
I am relieved to know its not just me, I was thinking I haven't seen behaviour like this in a decade ;)
Thank you all.
You mean this?
If anyone needs a temporary workaround:
Add this method to CCEffectRenderPassInputs in CCEffect.m: (goes at line 226 on my version):
// Hack to get around a compiler problem with the direct obj.verts = that corrupts the stack and crashes hard on 32 bit devices
// See http://forum.cocos2d-spritebuilder.org/t/cceffectbrightness-crashed-on-iphone4s/17124
- (void)verts_setter:(CCSpriteVertexes*)svp
{
_verts = *svp;
}
And declare it in CCEffect_Private.h: (line 132 for me): - (void)verts_setter:(CCSpriteVertexes*)svp;
Then in CCEffectRenderer.m around line 275 replace:
renderPassInputs.verts = padVertices(sprite.vertexes, effect.padding, tc1, tc2);
with
CCSpriteVertexes paddedVerts = padVertices(sprite.vertexes, effect.padding, tc1, tc2);
[renderPassInputs verts_setter:&paddedVerts];
It basically stops the code using the automatic setter for the CCEffectRenderPassInputs verts property which can't seem to handle the 192 byte structure being passed in (if you override the setter the stack is corrupted on entry). Passing 192 bytes by value is a bit OTT anyway but thats for another day. Hopefully a cleaner way to solve the problem will be found.
On 03 May 2015, at 14:14, EnlightenedOne notifications@github.com wrote:
Hi there is there any chance someone can get an extract from the workaround posted somewhere more exposed on the forum? Logged in the forum says "Sorry, you don't have access to that topic!" and the newer link post domain change shows the Discourse logo and: "The page you requested doesn't exist or is private.". I understand that the nature of the problem is an issue with the structs copying of value references between methods or simply put assignment of complex struct objects.
I did manage to render my own quick fix but it can probably be refined:
CCSpriteVertexes verts = padVertices(sprite.vertexes, effect.padding, tc1, tc2);
[renderPassInputs setVerts:&verts];-(CCSpriteVertexes)getVerts {
return verts;
}
-(void)setVerts:(CCSpriteVertexes*)newVerts {
verts.bl = newVerts->bl;
verts.br = newVerts->br;
verts.tr = newVerts->tr;
verts.tl = newVerts->tl;
}I am relieved to know its not just me, I was thinking I haven't seen behaviour a compiler behave like this in a decade ;)
Thank you all.
—
Reply to this email directly or view it on GitHub #1301 (comment).
Yeah that is much cleaner, thank you :) not sure why I cannot get access to forum topics via links, it just shows the main forum page with the pinned topics and such.
Btw official forum is back up and running. DAMN that was a struggle
forum.cocos2d-objc.org http://forum.cocos2d-objc.org/
On 03 May 2015, at 14:30, EnlightenedOne notifications@github.com wrote:
Yeah that is much cleaner, thank you :) not sure why I cannot get access to forum topics via links, it just shows the main forum page with the pinned topics and such.
—
Reply to this email directly or view it on GitHub #1301 (comment).
FWIW, I just received an automated message from Apple saying that my bug report for this issue is a duplicate of another bug. This is good because we're not the only people seeing this issue. Also, based on my reading of the status it looks like the bug that I duplicated is already closed (see below).
Sadly, when I try to search for the duplicate bug to confirm this, I can't see it. In my experience this is because I don't have the necessary privileges but I suppose it could be because it's already closed.
So I think it's already fixed?
Hmmm ... I guess, that even if the bug is closed, it will not work until next release of Xcode?
I am pretty sure I am running latest version, and that the bug is still here.
Yup. My guess is that it's fixed in Apple's internal source tree but we won't see it out here in the wild until some future release of Xcode.
FWIW, I just checked this issue with the newly released Xcode 6.3.2 (6D2105) and I still see this problem. This is both in cocos and in the standalone test case.
We still have the same problem with the latest version of Xcode (6.4).
This issue is closed, it means that it is fixed for you?
Yeah, problem will be fixed in next release
great ! thanks
