2010-07-11 92 views
2

我有一個跨平臺庫,只有在iPhone上有奇怪的問題,只有在釋放。靜態const初始化iPhone /發行

// .h 
class cColor 
{ 
public: 
    static const cColor Red; 
    static const cColor Green; 
    static const cColor Blue; 

    u8 r; 
    u8 g; 
    u8 b; 
    u8 a; 

    inline cColor(...) : ... { } 
}; 

// .cpp 
const cColor cColor::Red(0xFF, 0x00, 0x00); 
const cColor cColor::Green(0x00, 0xFF, 0x00); 
const cColor cColor::Blue(0x00, 0x00, 0xFF); 

它看起來像一個初始化順序失敗,但問題不是靜態方法,但後來在程序中。所有的cColor :: Red,Green,Blue都被設置爲0.實際上,我在構造函數的{}中放置了一些printf,它不打印任何東西,但可能它沒有問題,因爲它在全局初始化過程中。現在最糟糕的部分是:庫在Release中工作,直到最近我添加了幾個函數(200-300行),甚至沒有被執行的Objective-C代碼。只是從代碼大小切割我可以解決這個問題,但這不是我真正的選擇。此外,應用程序不是那麼大,內存不能成爲問題。

Btw cColor包含在庫中的預編譯頭文件中,後來在使用該庫的應用程序中。

幫助!我真的沒有想法。


編輯:下面是詳細信息...

我只移動了初始化代碼從圖書館到我的應用程序現在 常數得到正確初始化。

我真的認爲鏈接器搞亂了一些東西。

任何想法?

+0

有什麼症狀? – 2010-07-11 09:14:11

+0

所有靜態顏色的rgba值爲0.縮進器工作得很好,除了e靜態常量。 – Aleks 2010-07-11 18:23:14

+0

通過刪除足夠多的*任意*代碼或刪除* Objective-C *代碼,您現在可以再次運行它。 – 2010-07-11 22:34:47

回答

0

我確信這是一個鏈接器錯誤。我剛剛發現了一件非常愚蠢的工作。我將一個內聯函數從cColor類移到了cColor.cpp。除了靜態常量初始化之外,我在cColor.cpp中沒有其他任何東西。

我的猜測是,因爲在某些情況下,鏈接器決定忽略它,因此在翻譯單元中沒有其他內容。

我可能會將此發送給蘋果,以瞭解他們對它的看法。

P.S.只是爲了清楚我最初的想法是這是內存損壞,但我的庫/應用程序中沒有任何靜態內存分配。此外,我還測試了具有不同調試功能的多內存管理器的代碼,代碼甚至是免費的。

1

您可以輕鬆地防止靜態初始化順序的悲劇:http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.15

 
// .h 
class cColor 
{ 
public: 
    static const cColor& Red(); 
    static const cColor& Green(); 
    static const cColor& Blue(); 

    u8 r; 
    u8 g; 
    u8 b; 
    u8 a; 

    inline cColor(...) : ... { } 
}; 

// .cpp 
const cColor& cColor::Red() { 
    static cColor* redColor = new Color(0xFF, 0x00, 0x00); 
    return *redColor; 
}; 

/* etc */ 

我不知道這是否與您的症狀有助於雖然。

+0

我不認爲我的問題是初始化失敗,而不是初始化。我也知道這個解決方案,它會在我的情況下工作,但它比靜態常量要慢,因爲如果靜態變量被初始化,每次調用都會檢查它。 – Aleks 2010-07-11 16:13:56

+0

@Alex:你爲什麼認爲每次調用代碼時都會檢查它?你不認爲編譯器作者想到這一點,並已經添加了適當的優化! – 2010-07-11 19:47:47

+0

@LumpN:爲什麼動態創建顏色!只需要一個靜態的Color對象。 'static cColor red(0xFF,0x00,0x00);'它將在首次使用時正確創建,而不像您的代碼在應用程序關閉時將被正確銷燬。 – 2010-07-11 19:49:20

0

這是庫中靜態inits的常見情況。具有靜態初始化的代碼必須鏈接到主應用程序中。一個庫僅僅是一個.o文件的集合,並且在鏈接時,鏈接器選擇它想要包含到最終可執行文件中的哪個.o文件。如果你的主應用程序沒有引用這些變量,那麼鏈接器將確定目標代碼是未使用的,所以.o不會被拉入,因此初始化程序不會初始化。快速測試是在您的主要exe源文件中引用它們(不在您的庫中)或嘗試使用-Wl,-whole-archive-force_load標誌來gcc強制包含庫中的所有.o對象。

+0

變量用於庫和可執行文件中。主要的問題是在添加實現的objective-c代碼後出現問題。我可以通過刪除大約200行的任何目標C代碼來修復它。如果會有任何變化,我會對這些標誌進行防衛測試。 – Aleks 2010-07-12 00:59:17