2011-08-05 16 views
4

背景:我們正在使用Keil來編譯我們的恩智浦LPC2458項目。在Keil的RealView RTOS上有很多任務正在運行。有創建的堆棧空間,正在分配給每個任務。沒有默認創建堆和我想避免它,因爲我們買不起的代碼空間開銷和「垃圾收集」防止爲嵌入式項目編譯malloc/free

目的的成本:在嵌入式代碼使用C++不使用堆。 Keil提供了阻止malloc()和free()調用被鏈接的#pragma(__use_no_heap)。

解決方案:我試着用私有靜態指針創建一個單例。我的希望是new()不會被調用,因爲我在getDLMData()中聲明dlmData爲static。由於某些原因,鏈接器仍然聲明malloc()和free()被調用。我有一個私人運算符new()和一個私有運算符delete()的想法,然後在重載函數中聲明dlmData爲static。由於某種原因,它不工作。我究竟做錯了什麼?

//class declaration 
    class DataLogMaintenanceData 
    { 
    public: 
     static DataLogMaintenanceData* getDLMData(); 
     ~DataLogMaintenanceData() 
     { instanceFlag = FALSE; } 
    protected: 
     DataLogMaintenaceData(); //constructor declared protected to avoid poly 
    private: 
     static Boolean instanceFlag; 
     static DataLogMaintenceData *DLMData; 
    } 

    //set these to NULL when the code is first started 
    Boolean DataLogMaintenanceData::instanceFlag = FALSE; 
    DataLogMaintenanceData *DataLogMaintenaceData::DLMData = NULL;  

    //class functions 
    DataLogMaintenanceData *DataLogMaintenanceData::getDLMData() 
    { 
     if (FALSE == instanceFlag) 
     { 
      static DataLogMaintenanceData dlmData; 
      DLMData = &dlmData; 
      instanceFlag = TRUE; 
      return DLMData; 
     } 
     else 
     { 
      return DLMData; 
     } 
    } 

    void InitDataLog (void) 
    { 
     DataLogMaintenanceData *dlmData; 
     dlmData = DataLogMaintenanceData::getDLMData(); 
     // to avoid dlmData warning 
     dlmData = dlmData; 
    } 

    //ACTUAL TASK 
    __task DataLog() 
    { 
     .. .. .. code to initialize stuff 

     InitDataLog(); 

     .. .. ..more stuff 
    } 

出於某種原因,我能得到這個編譯的唯一途徑,是創建一個堆空間,然後讓malloc()和free()的調用被編譯到項目中。正如所料,「靜態」盟友定義的對象dlmData駐留在分配給dataLog.o模塊的RAM空間中(即,它不在HEAP中)。

我想不通,我檢查了Google,我錯過了什麼?在編譯純對象時,C++可能會繞過malloc()和free()嗎?我知道我可以替換RTOS的malloc()和free()來實現,但是我想避免在不使用的代碼中進行編譯。

+0

只需將'DLMData'設置爲文件級'靜態DataLogMaintenanceData *'。這會自動初始化爲「NULL」,因此您不需要另一個冗餘'instanceFlag'。 'InitDataLog'中的堆棧變量'dlmData'有什麼意義?這段代碼很混亂。 – MSalters

+1

C++中沒有垃圾收集。你確定性地管理你自己的記憶。 –

+0

單身 - >收穫你播種,imo。 – Puppy

回答

2

也許我們沒有看到的一些代碼調用了一個在幕後調用malloc的函數。

http://www.keil.com/support/man/docs/armlib/armlib_CJAIJCJI.htm您可以使用鏈接線上的--verbose --list=out.txt來獲取有關malloc調用者的詳細信息。

+0

我試過那個馬克,沒有成功;我對Keil有一個問題。 –

0

從您發佈的代碼中,我看不到任何想要在堆上分配內存的內容。是否有任何隱式轉換髮生?如果你根本沒有這門課而編譯呢?

你可以做什麼:在調試器下運行

1)(假設你可以建立一個可運行的圖像,也許在模擬器上),設置在malloc的一個斷點,檢查堆棧

2)提供您的自己的malloc並免費使鏈接器開心,然後重複步驟1.

您可能會發現需要鏈接到不同版本的C運行時啓動。在最壞的情況下,如果malloc/free的調用次數有限,你可以推出自己的版本,這將給調用者一些預先分配的內存 - 但希望這不是必需的。

+0

所以我運行調試器,發現malloc被稱爲__rt_lib_init_return(初始化實時庫?)的一部分。這真讓我困惑。我讀過AEABI,似乎malloc調用是這種靜態聲明的標準嗎?這違背了我所瞭解的有關靜態對象聲明的知識。這似乎是我不明白一些基本的東西。 –

+0

我會給Keil發一封電子郵件。如果你想在沒有堆的情況下運行,你可能需要鏈接到不同版本的運行時庫。 – MaximG

0

包含在Keil安裝中的是一組PDF文件(文檔ID DUI0475A),標題爲「使用ARM C和C++庫和浮點支持」。它討論了在多個地方使用堆(並防止它的使用)。

具體而言,請查閱第2.64節「避免使用ARM提供的堆和堆使用庫函數」,其中提供了許多有用的信息。該節中的有趣的文字:

您可以參考__use_no_heap__use_no_heap_region符號 您的代碼以保證沒有使用堆的函數從 ARM庫鏈接英寸

__use_no_heap反對使用malloc衛士(),realloc()的,自由(), 和一個使用這些功能中的任何功能。例如,calloc()和 其他stdio函數。

__use_no_heap_region具有相同的屬性__use_no_heap,但在 另外,防止使用堆內存區的其他東西守衛。 例如,如果將main()聲明爲帶參數的函數,則堆區域將用於收集argc和argv。

因爲你的問題是關於如何防止malloc()被調用/使用,這可能讓你在正確的軌道上。