Question about touchesEnded in EAGLView.mm

Hi all,

I believe I might have stumbled upon a possible issue in the following routine in EAGLView.mm. This source has been taken from the stable release cocos2d-0.99.5-x-0.8.1.

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    cocos2d::NSSet set;
    for (UITouch *touch in touches) {
            NSNumber *index = (NSNumber*)CFDictionaryGetValue(touchesIntergerDict, touch);
            if (! index) {
                // if the index doesn't exist, it is an error
                return;
            }

                cocos2d::CCTouch *pTouch = s_pTouches[[index intValue]];
                if (! pTouch) {
                    // if the pTouch is null, it is an error
                    return;
                }

        float x = [touch locationInView: [touch view]].x;
        float y = [touch locationInView: [touch view]].y;
        int tapCount = [touch tapCount];
        pTouch->SetTouchInfo(0, tapCount, x, y);

        set.addObject(pTouch);
                CFDictionaryRemoveValue(touchesIntergerDict, touch);
                pTouch->release();                                    //Could this lead to a dangling pointer?
                s_pTouches[[index intValue]] = NULL;
                [self removeUsedIndexBit:[index intValue]];
    }

    cocos2d::CCDirector::sharedDirector()->getOpenGLView()->touchesEnded(&set);
}

Since the std::set inserts a pointer to a CCTouch, it doesn’t create a copy of the CCTouch data. I came across this issue while doing the following:

void MainGame::ccTouchesEnded(CCSet* touches, CCEvent* event)
{
    if(touches->count() == 1)
    {
        CCTouch *const touch1       = dynamic_cast(touches->anyObject());
        assert(touch1);

        CCTouch *const touch2       = (CCTouch *)touches->anyObject();
        ....
    }
}

The dynamic_cast for touch1 would fail but the C-Style cast for touch2 would succeed but with undefined results.

dynamic_cast() works ok in win32. The win32 version also inserts a pointer of CCTouch into CCSet. It is the matter of gcc, but I don’t know how to resolve it. Because the build settings:

Symbols Hidden by Default
Inline Functions Hidden

are not on.

Hi Zhang,

Thanks for replying. If I understand the problem correctly, this is simply a case of the pTouch data being prematurely released before the CCSet is being sent to the touchesEnded() routine of CCEGLView. I propose the following solution to this. In EAGLView.mm:

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    cocos2d::CCSet set;

    for (UITouch *touch in touches) {
            NSNumber *index = (NSNumber*)CFDictionaryGetValue(touchesIntergerDict, touch);
            if (! index) {
                // if the index doesn't exist, it is an error
                return;
            }

                cocos2d::CCTouch *pTouch = s_pTouches[[index intValue]];
                if (! pTouch) {
                    // if the pTouch is null, it is an error
                    return;
                }

        float x = [touch locationInView: [touch view]].x;
        float y = [touch locationInView: [touch view]].y;
        pTouch->SetTouchInfo(0, x, y);

        set.addObject(pTouch);
                CFDictionaryRemoveValue(touchesIntergerDict, touch);                
                s_pTouches[[index intValue]] = NULL;
                [self removeUsedIndexBit:[index intValue]];
    }

    cocos2d::CCDirector::sharedDirector()->getOpenGLView()->touchesEnded(&set);
        //Now release the contents of the set.
    for(cocos2d::CCSetIterator iter = set.begin(); iter != set.end(); ++iter)
    {
        (*iter)->release();
    }
}

Do let me know if this makes sense.

this is simply a case of the pTouch data being prematurely released before the CCSet is being sent to the touchesEnded routine of CCEGLView

No, it is not true. When pTouch is added into a set, the reference of pTouch is increased.