在keil C下直接使用malloc是沒問題,Keil C會自動幫你分配記憶體空間,但是到了MDK for ARM 就不是這個樣子了.
為何要使用malloc?當然是有其好處,不然練練功也不錯,對於軟體開發上,用慣了物件導向的設計者,
對於韌體開發真是有一股難以說出的痛,明明許多程式碼可以使用物件來創建,
卻因為開發環境(工具)相當難以掌控及操控性不佳,導致開發速度變慢和不易偵錯的問題發生.
習慣微軟的開發工具(Visual studio .NET)才知道這工具的強大及好用,用了MDK才知道自己的脾氣不夠好.
剛開始開發軔體時直覺好像在讀書時交作業般的方式再寫程式.
當然小程式還好,當程式夠大時,又持續要修改時, 漸漸的就陷入了程式碼的漩渦中.
你只能隨著旋渦被慢慢捲入,幸運的話你可以找到對的點切出此困境,不幸的話你就陷入了漩渦之中漸漸的消失.
在學習軟體的過程中都會碰到Stack(堆疊)和Heap(堆積),這兩個的定義是不一樣的.
heap:是由malloc之類函數分配的空間所在地。地址是由低向高增長的。
例如malloc 與new出來的東西用指針指向了它,所指的地方就是heap。
stack:是自動分配變量,以及函數調用的時候所使用的一些空間。地址是由高向低減少的。就是我們平時所說的局部變數。
stack區中的局部數據佔有的空間在函數結束後會自動釋放,而heap中的要由我們手動釋放。
另外stack中空間的分配一般在編譯時就知道大小了,而如果要在運行時分配空間,就要使用heap了。
/*------------- C#觀念 -------------------------------------------------
線程堆疊(Thread Stack)和托管堆(Managed Heap)
每個正在運行的程序(Program)都對應一個"進程"(Process),在一個進程內部,
可以有一個或多個"線程"(Thread),每個線程都擁有一塊記憶體"空間",稱為" 線程堆疊",大小為1MB.
用於保存自身的一些數據,比如線程函數中定義局部變數.線程函數調用時傳送的參數值等.
這部分記憶體空間的分配與回收不需要程式設計者干涉.
另一塊記憶體區域稱為堆.在.NET這種托管的環境下.堆由CLR進行管理,所已將其稱為"托管堆".
用new關鍵字創造物件時,分配給物件的記憶體單元就位於托管堆中.
※值類型變數所佔用的記憶體是在線程堆疊中分配的.
※參考類型變數引用的物件所占用的記憶體是在托管堆中分配的.
堆疊(Stack)和堆積(Heap) 是存放資料的記憶體分成兩種不同的管理機制。
堆疊:數值型別的家。
堆積:參考型別的家。
每當new 出一個物件,例如:
Myclass cls = new
MyClass();
物件參照 cls 就擺放在堆疊中,而new出來的物件MyClass()就擺在堆積中。
當cls的生命周期結束,也就是MyClass()沒人使用時,堆積中的cls
就會被註明為沒人使用,系統會不定時的把沒人使用的cls清空。
------------------------------------------------------------------------------------------*/
以上相當容易的觀念,在某些開發工具上使用起來相當容易,可是在MDK for ARM,就需要一些設定來解決.
首先設定Heap Size,預設是 0x0000 0000,修改成我們想要的大小.
main()
{
char *p1; //指標放在stack區。
p1 = (char *)malloc(10);
//分配得來得10 bytes的區域就在heap區。
}
經過如此簡單的設定就可使用malloc.
void main()
{
char *p2;
_init_alloc(0x40001500,0x40001600); //可有可無,如果設定起始位址和結束位址,
//P2指標就從0x4000 1500開始,否則預設從0x0000 0000開始.
p2 = (char *)malloc(10);
//當要佔用空間太大時,須修改 _init_alloc(0x40000500,0x40001600)
if(!(p2=(char*)malloc(1000)))
{
return 0;
}
}
如果使用未分配區塊<100時,使用 Heap1既可.一個區塊最小為4 bytes,同時還會消費掉另外 4 bytes.
如果區塊有數百個則使用 Heap2.
使用Heap2須宣告:
#pragma import(__use_realtime_heap)
如果堆積的空間超過16MB則要重新定義
__user_heap_extent()
留言列表