简体   繁体   中英

EXC_BAD_ACCESS upon accessing a static member?

I've developed a game on Cocos2d-x v2 platform I started on Android, after completely finishing the coding on Eclipse I used the same code on Xcode to create and iOS version. After adding all the required libraries, I succeeded in compiling the code. However, the game hangs the moment it runs on an iOS device, although it runs without any problem on Android. I tried both the emulator and an iPod, but I always get an EXC_BAD_ACCESS when accessing a static member from a static method. The static member would always point to 0x0!! Here's an excerpt from the code:\\

AppDelegate.cpp

#include "AppDelegate.h"
#include "NASEncData.h"
AppDelegate::AppDelegate()
{
    ep = NASEncData::sharedUserData();
}

NASEncData.h

namespace CocosNas
{
    class NASEncData : public CCObject
    {
public:
        static NASEncData* sharedUserData();

private:
        NASEncData();

        static void initXMLFilePath();

        static std::string m_sFilePath;
    }
}

NASEncData.cpp

#include "NASEncData.h"


NASEncData* NASEncData::sharedUserData()
{
    initXMLFilePath();

    // only create xml file one time
    // the file exists after the programe exit
    if ((! isXMLFileExist()) && (! createXMLFile()))
    {
        return NULL;
    }

    if (! m_spUserData)
    {
        m_spUserData = new NASEncData();
    }

    return m_spUserData;
}

void NASEncData::initXMLFilePath()
{
    if (! m_sbIsFilePathInitialized)
    {
        m_sFilePath += CCFileUtils::sharedFileUtils()->getWriteablePath() + NASENCDATA_XML_FILE_NAME;                  <----error happens here
        m_sbIsFilePathInitialized = true;
    }   
}

Based on the comments on your question, your problem could be the initialization order of static data. To be more specific, I think it is possible that the static AppDelegate instance gets created and initialized before the static members in the NASEncData . And this problem could also explain the fact that you are seeing different behavior on different platform, because the initialization order of unrelated static data are compiler and linker dependent.

To fix this, you could change your NASEncData like this: (note that this is only one possible fix, although if the initialization order of statics is really your problem, I think this is the simplest and best solution, apart from redesigning your code so that you don't have to rely on static members.)

NASEncData.h

namespace CocosNas
{
    class NASEncData : public CCObject
    {
    public:
        static NASEncData* sharedUserData();

    private:
        NASEncData();

        static void initXMLFilePath();

        // Note how the stuff below this line have changed
        struct StaticData
        {
            std::string m_sFilePath;
            // Put other static members here
            //   (e.g. m_sbIsFilePathInitialized, m_spUserData, etc.)
            // Put a proper constructor here if needed
        };

        static StaticData & getStaticData ()
        {
            static StaticData s_data;
            return s_data;
        }
    }
}

NASEncData.cpp

void NASEncData::initXMLFilePath()
{
    if (! m_sbIsFilePathInitialized)
    {
        // Note the change in accessing m_sFilePath
        // You should access all your static members like this
        getStaticData().m_sFilePath +=
            CCFileUtils::sharedFileUtils()->getWriteablePath() +
            NASENCDATA_XML_FILE_NAME;
        getStaticData().m_sbIsFilePathInitialized = true;
    }   
}

What this does in ensure that when you try and access your static member data, they have already been initialized. This happens because all your static member data are now defined inside a function as static, and for accessing them you have to call that function, and the compiler generates code to make sure that the first time that function is invoked (and only the first time) your data is constructed and initialized properly, which in turn means that the first time you actually try to access this data, whenever and wherever that may be from, your data is properly initialized.

实际上,这确实是一个初始化问题,我只需要将代码从构造移动到bool AppDelegate :: applicationDidFinishLaunching()就可以了!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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