2016-04-29 25 views
2

在我們的項目中,我們使用了外部RAM。當通常調用構造函數時,它在啓動時不會被初始化或安全使用。由於這個原因,當一個類需要在外部RAM中實例化時,構造器需要被阻止運行,直到外部RAM準備好使用。這樣做的最好方法是什麼?推遲C++中的靜態變量構造

我能想到的一個選擇是爲具有正確大小和對齊方式的對象分配一些空間,然後在此位置上調用新放置位置。

static ALTRAM union 
{ 
    UINT64 alignment; 
    UINT8 space[sizeof(ClassName)] 
}spaceHolder; 
ClassName* classInstance = NULL; 
... 
classInstance new (&spaceHolder) ClassName(); 

建議的另一個選項是將對象實例化爲傳遞指向實例的指針的函數中的靜態函數對象。我的關注點在於,標準允許在第一次調用函數時調用構造函數,但似乎並不需要所有編譯器都這樣做。 See bold text from the standard

static ClassName& GetInstance() 
{ 
    static ALTRAM ClassName instance; 
    return instance; 
} 

該項目針對Win32 VC++和Keil for ARM進行編譯,但僅對ARM有此要求。是否有編譯指示或其他方法來防止構造函數被調用?

我正在尋找不需要修改類的解決方案。

更新

謝謝大家對您的回覆也非常有幫助。我得出以下結論:

  1. 體系結構應該在應用程序運行之前初始化硬件。這個問題引發了很多關於我們團隊的討論,它很可能會被修復。
  2. 有些人更喜歡安置新方法。
  3. 對於另一種方法,C++標準要求在第一次執行函數時調用構造函數,所以這應該是可靠和便攜的解決方案。
+0

放置新方法有什麼問題? – Barmar

+0

操作系統的工作在準備好之前不應該使用這個內存嗎?你不應該在操作系統級別而不是應用級別上解決這個問題嗎? –

+0

@JesperJuhl是的,操作系統級別的解決方案正在調查中,但還沒有。 – colojaro

回答

0

由於已建議,預留的存儲和使用位置的新塊:

char object[sizeof(ClassName)]; 
new (&object) ClassName(); 
+0

@Quentin - 謝謝。固定。 –

0

如果你關心的編譯器被允許建立靜態局部對象早於需要,您可以隨時添加了一個間接層:支持嵌入式系統配備了C++環境初始化之前要進行初始化一些「啓動」示例代碼

ClassName &getInstance() { 
    static ClassName *instance(NULL); 
    if(!instance) instance = new ClassName; 
    return *instance; 
} 
+0

有沒有辦法做到這一點靜態分配在外部RAM而不是在堆上? – colojaro

+0

最有可能。例如,您可以使用placement'new'並添加一個預設爲true的靜態布爾標誌:'static ClassName * instance(ADDRESS);靜態布爾未定義(true); if(undefined){new(instance)ClassName; undefined = false; }'。 – bipll

0

許多編譯器。通常,這段代碼設置ARM堆棧寄存器和其他項目。代碼可能是彙編語言。你應該把你的內存初始化代碼放在這個「啓動」代碼中。