2012-05-15 25 views
2

我們使用Micrium的uC/OS-III RTOS。 我們試圖在RTOS上返回malloc的值。 當我們在RTOS啓動之前做一個99999的malloc(RAM太多)時,我們得到一個空指針,這正是我們所期望的。Micrium的μC/ OS-III RTOS中的Malloc

當我們在RTOS啓動時和任務中執行相同的malloc時,我們不會收到空指針,這是我們不期望的。 儘管此時系統確實凍結。

有沒有人對此有過解釋?

在此先感謝

編輯:

對於信息:我們使用瑞薩的RX62N微控制器和GNURX編譯

程序實際上不會凍結。該程序'認爲'它得到一個有用的指針(不是NULL指針),並繼續運行。在某一點上,程序將其程序計數器更改爲00000000並停止。所以它沒有進入Exception,因此我們無法捕捉它。

但是,在RTOS啓動和RTOS啓動之前調用malloc時會有所不同。不同之處在於深度彙編代碼爲malloc

在某點以下的指令當我們試圖分配太多的RAM BGTU.B指令不應分支,然後程序繼續ADD指令執行

CMP   R1,R7 
BGTU.B  0FFF802C0H 
ADD   R14,R7 

。當在啓動RTOS之前執行malloc,並且在之後執行時失敗時,此功能完好。

These are the values I get in several cases 

Outside RTOS (allocable number: 10) 
R1: 00008348 
R7: 00000014 

Outside RTOS (not allocable number: 9999) 
R1: 00008348 
R7: 00002718 

Inside RTOS (allocable number: 10) 
R1: FFFFF9D0 
R7: 00000014 

Inside RTOS (not allocable number: 9999) 
R1: FFFFF9D0 
R7: 00002718 

我希望整個情況是清楚的,我試圖解釋它一樣好,我可以:P提前

感謝

+1

它「凍結」在哪裏?你的調試器告訴你關於位置和調用堆棧的信息?根據您的目標,無效的地址訪問可能會導致異常。默認的異常處理程序通常是空循環 - 實現更有用的東西。請注意,malloc()和free()通常本質上不是線程安全的。一些庫提供鉤子來使用操作系統的互斥體使一些非線程安全的函數成爲線程安全的。檢查你的庫文檔。 – Clifford

+0

查看頂部克利福德的編輯! = D – Davey

+0

該分支取決於CMP操作的結果,因此您不得不問自己爲什麼分支(這是因爲R1> R7),而是爲什麼R1和R7中的值與您預期的不同。 – Clifford

回答

0

但在所有的插圖情況下,第二種情況R7出現包含分配的大小(請求的大小+對齊+堆管理數據)。直觀上R7 = 0x2718將對應於999個字節的分配,所以我懷疑這可能是一個錯字。

R1我猜會包含內存將被分配的堆塊的大小,因爲那時CMP會有意義。如果塊不夠大,則會失敗。

但是,當RTOS運行時,R1中的值變得非常大,顯然是不正確的。如果你的堆損壞了,可能會發生這種情況。如果您超出了在堆上分配的緩衝區,則會發生這種情況。如果從堆中分配線程堆棧,並且堆棧太小,則會產生相同的效果。您的線程堆棧必須足夠大,以適應最壞情況的調用堆棧,以及RTOS支持上下文切換所需的任何堆棧。即使你沒有從堆中分配堆棧,如果一個線程堆棧與堆內存相鄰,堆棧溢出也會產生相同的效果。

堆可能被破壞的另一種方式是通過在多個線程中同時執行分配或釋放而不強制執行互斥或臨界區。標準庫堆管理不太可能是線程安全的,除非您已經做了必要的修改以將其與RTOS集成 - 如果RTOS和標準庫來自同一供應商(例如,如果兩者都提供與編譯器)。

+0

我們現在發現了一個新的函數來分配內存,只有釋放是一個問題。可能Micrium已經知道這是一個問題。因爲這個新功能在Micrium書中沒有任何地方可以發現,所以我們最近才發現這個功能。這個RTOS可能是第一個選擇,我們沒有研究它,因爲我們現在發現了這個新功能。釋放問題問在http://stackoverflow.com/questions/10717409/allocation-and-free-in-micrim-c-os-iii-rtos – Davey

0

我們發現在UCOS-III操作系統啓動之前調用malloc可以正常工作。從線程調用時,它會失敗並返回一個NULL指針。我懷疑這是由於檢查堆棧,當在可以有任意放置堆棧的線程中運行時,堆棧當然是無效的。 我可以在映射文件中看到該庫引用特定的sbrk(lib_a-sbrk.o)函數,並且無法找到該函數的任何源。 衆所周知,默認的GNU sbrk函數將檢查當前的堆棧指針,以查看當前中斷是否超出了SP並失敗。

不幸的是,我們必須依賴於malloc,因爲我們使用的是複雜的C++庫,因爲我們有MB的內存,我們不關心碎片,我們只是希望m​​alloc能夠工作。實際上我們並不關心重入,因爲我們只在一個線程中使用malloc。

是否有可能闡明如何在庫中實現堆函數。我們正在使用ARM-9芯片。

+0

這應該被張貼爲[一個新的問題](http:// stackoverflow.com/questions/ask),而不是作爲現有問題的答案。 – xorspark