访问静态成员时EXC_BAD_ACCESS?

时间:2013-03-11 06:15:24

标签: c++ xcode exc-bad-access cocos2d-x static-members

我在Cocos2d-x v2平台上开发了一款游戏 我开始使用Android,在完成Eclipse上的编码后,我在Xcode上使用了相同的代码来创建和iOS版本。 添加完所有必需的库后,我成功编译了代码。然而,游戏在iOS设备上运行时就会挂起,尽管它在Android上没有任何问题。 我尝试了模拟器和iPod,但是当从静态方法访问静态成员时,我总是得到一个EXC_BAD_ACCESS。静态成员总是指向0x0 !! 以下是代码的摘录:\

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;
    }   
}

2 个答案:

答案 0 :(得分:0)

根据您对问题的评论,您的问题可能是静态数据的初始化顺序。更具体地说,我认为静态AppDelegate实例有可能在NASEncData中的静态成员之前创建和初始化。此问题还可以解释您在不同平台上看到不同行为的事实,因为不相关的静态数据的初始化顺序是编译器和链接器相关的。

要解决此问题,您可以像这样更改NASEncData :(请注意,这只是一种可能的修复,但如果静态的初始化顺序确实是您的问题,我认为这是最简单和最佳的解决方案,除了重新设计代码,以便您不必依赖静态成员。)

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;
    }   
}

这样做可以确保在您尝试访问静态成员数据时,它们已经初始化。发生这种情况是因为所有静态成员数据现在都在函数内部定义为静态,并且为了访问它们,您必须调用该函数,并且编译器生成代码以确保第一次调用该函数(并且仅在第一次调用时) )您的数据被正确构建和初始化,这反过来意味着您第一次真正尝试访问此数据时,无论何时何地,您的数据都已正确初始化。

答案 1 :(得分:0)

这确实是一个初始化问题,我只需将代码从构造移动到bool AppDelegate :: applicationDidFinishLaunching()并且它有效!