2013-03-11 5 views
1

Я разработал игру на платформе Cocos2d-x v2 Я начал работу на Android после полного завершения кодирования на Eclipse. Я использовал тот же код на Xcode для создания и версии iOS. После добавления всех необходимых библиотек мне удалось скомпилировать код. Тем не менее, игра висит в момент ее запуска на устройстве iOS, хотя она работает без каких-либо проблем на Android. Я пробовал как эмулятор, так и iPod, но я всегда получаю EXC_BAD_ACCESS при доступе к статическому элементу из статического метода. Статический член всегда указывал бы на 0x0 !! Вот отрывок из кода: \EXC_BAD_ACCESS при доступе к статическому члену?

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

Возможно, экземпляр 'AppDelegate' вызывает конструктор для статической переменной? – yzt

+0

в версии iOS есть файл .mm, который определяет следующее: static AppDelegate s_sharedApplication; - это нормально? – FiFo

+0

Я думаю, что это может быть вашей проблемой. – yzt

ответ

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

Что это делает, чтобы убедиться, что при попытке доступа к вашим статическим данным элемента, они уже инициализированы. Это происходит потому, что все ваши данные статического члена теперь определены внутри функции как статические, и для доступа к ним вы должны вызвать эту функцию, а компилятор генерирует код, чтобы убедиться, что в первый раз эта функция вызывается (и только в первый раз) ваши данные строятся и инициализируются должным образом, что, в свою очередь, означает, что в первый раз, когда вы на самом деле пытаетесь получить доступ к этим данным, когда и где бы это ни было, ваши данные были правильно инициализированы.

0

Это была действительно проблема инициализации, которую мне просто пришлось переместить код из конструкции в bool AppDelegate :: applicationDidFinishLaunching(), и это сработало!

+0

ОК, но это звучит как очень конкретное решение. Помните, что проблемы порядка инициализации * могут * быть исправлены в хорошем смысле в дизайне и в реализации. – yzt

+0

Я не думаю, что это конкретный случай. Cocos2D-X - хорошо известная платформа, и я думаю, что решение, о котором я упомянул, поможет многим людям. – FiFo

+0

Ну, вы, конечно, правы. Это помогает всем, кто использует Cocos2D-X на iOS, и, возможно, даже на других платформах. Но так как каждый серьезный программист на C/C++ попадает в ловушку статического инициализационного процесса однажды или даже больше в своей карьере, общее исправление должно/будет применимо к большинству из них и во многих других ситуациях. Исправление, которое вы придумали, совершенно законно и применимо, но оно не делает ничего, чтобы исправить * причину * проблемы. Он перемещает только некоторый код, поэтому вы не запускаете его * пока *. – yzt

Смежные вопросы