Error "Cast from pointer to smaller type 'int' loses information" in EAGLView.mm when update Xcode to 5.1 (5B130a)
Asked Answered
C

6

32

Yesterday, I updated Xcode to the newest version (5.1 (5B130a)) to compatible with iOS 7.1. Then I build my project, I get the error "Cast from pointer to smaller type 'int' loses information" in EAGLView.mm file (line 408) when 64-bit simulators (e.g.: iPhone Retina 4-inch 64-bit) is selected.

I'm using cocos2d-x-2.2.2. Before I update Xcode, my project still can build and run normally with all devices.

Thanks for all recommendation.

Update: Today, i download the latest version of cocos2d-x (cocos2d-x 2.2.3). But the problem has still happened.

Here is some piece of code where that error occur:

/cocos2d-x-2.2.2/cocos2dx/platform/ios/EAGLView.mm:408:18: Cast from pointer to smaller type 'int' loses information

// Pass the touches to the superview
#pragma mark EAGLView - Touch Delegate
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    if (isKeyboardShown_)
    {
        [self handleTouchesAfterKeyboardShow];
        return;
    }

    int ids[IOS_MAX_TOUCHES_COUNT] = {0};
    float xs[IOS_MAX_TOUCHES_COUNT] = {0.0f};
    float ys[IOS_MAX_TOUCHES_COUNT] = {0.0f};

    int i = 0;
    for (UITouch *touch in touches) {
        ids[i] = (int)touch;     // error occur here
        xs[i] = [touch locationInView: [touch view]].x * view.contentScaleFactor;;
        ys[i] = [touch locationInView: [touch view]].y * view.contentScaleFactor;;
        ++i;
    }
    cocos2d::CCEGLView::sharedOpenGLView()->handleTouchesBegin(i, ids, xs, ys);
}
Caudate answered 15/3, 2014 at 3:10 Comment(7)
If pointers are 64 bits and ints are 32 bits, an int is too small to hold a pointer value.Eastwards
Thanks. But I don't want to edit code in "EAGLView.mm" because it's a "library file". Anw, the project still build and run normally when i use Xcode 5.0 with iOS 7.0. The problem just occur with Xcode 5.1Caudate
The problem was there before, you just are being notified of it. whether it was an actual problem is a different matter though.Jeddy
@LearnCocos2D: so, how can i "overcome" the error without editing any not-my-code or in-library-file lines?Caudate
If it's anything like cocos2d-iphone v2.x and just based on this slice of code in a core class I wager it's safe to say that cocos2d-x 2.x also is not compatible with 64 bit code, and you can expect all kinds of issues (not just compile-time but also runtime). There's probably little you can do except look or hope for a fixed 2.x version or upgrade to 3.x (I would assume it's 64-bit safe but this is just a guess, do research this issue before you upgrade). The only alternative is really to take time and fix all 64-bit code issues, of which there may be some non-trivial issues.Jeddy
Actually, I tried to build and run my project with cocos2d-x 2.2.3 but the problem is still there. Let me try with 3.x version and report if it works.Caudate
use this line of code ids[i] = (int)(size_t)touch; instead of ids[i] = (int)touchRosenkranz
B
51

Apparently the clang version in Xcode 5.1 and above is more strict about potential 32bit vs. 64 bit incompatibilities in source code than older clang versions have been. To be honest, I think, clang is too restrictive here. A sane compiler may throw a warning on lines like this but by no way it should throw an error, because this code is NOT wrong, it is just potentially error-prone, but can be perfectly valid.

The original code is

ids[i] = (int)touch;

with ids being an array of ints and touch being a pointer.

In a 64bit build a pointer is 64bit (contrary to a 32bit build, where it is 32bit), while an int is 32bit, so this assignment stores a 64bit value in a 32bit storage, which may result in a loss of information.

Therefore it is perfectly valid for the compiler to throw an error for a line like

ids[i] = touch;

However the actual code in question contains an explicit c-style cast to int. This explicit cast clearly tells the compiler "Shut up, I know that this code does not look correct, but I do know what I am doing".

So the compiler is very picky here and the correct solution to make the code compile again and still let it show the exact same behavior like in Xcode 5.0 is to first cast to an integer type with a size that matches the one of a pointer and to then do a second cast to the int that we actually want:

ids[i] = (int)(size_t)touch;

I am using size_t here, because it is always having the same size as a pointer, no matter the platform. A long long would not work for 32bit systems and a long would not work for 64 bit Windows (while 64bit Unix and Unix-like systems like OS X use the LP64 data model, in which a long is 64bit, 64bit Windows uses the LLP64 data model, in which a long has a size of 32bit (http://en.wikipedia.org/wiki/64-bit_computing#64-bit_data_models)).

Brickwork answered 20/11, 2014 at 16:20 Comment(2)
Casting (int)(size_t)boo instead (int)boo solved my problem. Thanks!Desireah
It solved my problem too. I wish that you write those answer first than the explanation.Rugger
B
9

I meet this problem too.

ids[i] = (int)touch; // error occur here => I change this to below.

ids[i] = (uintptr_t)touch;

Then i can continue compiling. Maybe you can try this too.

Bechtel answered 3/4, 2014 at 6:43 Comment(0)
P
2

XCode 5.1 is change all architecture to 64 bit.

you can just change architecture to support 32 bit compilation by all below in in Build Settings

  • use $(ARCHS_STANDARD_32_BIT) at Architecture instead of $(ARCHS_STANDARD)
  • remove arm64 at Valid Architectures

Hope it helps.

Persse answered 18/3, 2014 at 9:0 Comment(2)
Did i have to face to unexpected runtime issuesCaudate
i guess not, i've found another discussion on this - https://mcmap.net/q/257616/-xcode-5-and-ios-7-architecture-and-valid-architectures .or at least, i think cocos2d-x-3.0rc0 has fixed this issue already.Persse
F
2

You can fix this error by replacing this line of code.

ids[i] = (uint64_t)touch;

You should perform type conversion based on 64bit build system because the type "int" supports only -32768 ~ 32768.

Forrester answered 21/5, 2016 at 14:27 Comment(1)
"because the type "int" supports only -32768 ~ 32768" This is not true for any modern desktop or mobile OS or any OS that is targeted by cocos2d-x. On all of them int is 32bit, not 16bit.Brickwork
G
0

Surely the solution is to change the type of ids from int to type that is sufficiently large to hold a pointer.

I'm unfamiliar with XCode, but the solution should be something like follows:

Change the declaration of ids to:

intptr_t ids[IOS_MAX_TOUCHES_COUNT];

and the line producing the error to:

ids[i] = (intptr_t)touch;

Most of the "solutions" above can lose part of the pointer address when casting to a smaller type. If the value is ever used as pointer again that will prove to be an extremely bad idea.

Gyro answered 11/3, 2015 at 13:3 Comment(1)
You are correct, but cocos actually only uses that address as a unique id. Changing the type of ids would be the cleanest solution, but I decided against it when being confronted with this issue myself, as it only introduced a lot of issues with other code that is relying on ids being an int-array. Just re-enforcing the old behavior of Xcode 5.0 and earlier versions, that already cut away parts of the address by casting it to int, won't introduce any new bugs and avoids the need to learn and understand lots of implementation-internal cocos code.Brickwork
C
-2
ids[i] = (int)touch; put * and check it.
ids[i] = *(int *)touch;
Casimiracasimire answered 9/9, 2015 at 6:8 Comment(1)
This answer is incorrect for the reasons that have already been mentioned in the comment of https://mcmap.net/q/448291/-error-quot-cast-from-pointer-to-smaller-type-39-int-39-loses-information-quot-in-eaglview-mm-when-update-xcode-to-5-1-5b130a.Brickwork

© 2022 - 2024 — McMap. All rights reserved.