文章一、C語言的內存分配模型 1、程序代碼區:存放函數體的二進制代碼。 2、全局區數據區:全局數據區划分為三個區域。全局變量和靜態變量的存儲是放在一塊的,初始化的全局變量和靜態變量在一塊區域,未初始化的全局變量和未初始化的靜態變量在相鄰的另一塊區域。常量數據存放在另一個區域里。這些數據在程序結束后由系統釋放。我們所說的BSS段(bss segment)通常是指用來存放程序中未初始化的全局變量的一塊內存區域。BSS是英文Block Started by Symbol的簡稱。 3、棧區:由編譯器自動分配釋放,存放函數的參數值,局部變量的值等。其操作方式類似於數據結構中的棧。 4、堆區:一般由程序員分配釋放,若程序員不釋放,程序結束時可能由OS回收。注意它與數據結構中的堆是兩回事,分配方式倒是類似於鏈表,呵呵。 5、命令行參數區:存放命令行參數和環境變量的值。
關於局部的字符串常量是存放在全局的常量區還是棧區,不同的編譯器有不同的實現。可以通過匯編語言察看一下。不過vc環境下,局部常量就像局部變量一樣存儲於棧中,全局常量、字符常量存儲於文字常量區。TC在常量區。 在linux下:可以通過參數-c來編譯生成匯編文件。如: gcc -c *.c gcc *.o -Map test.txt -o test.elf 用文本編輯器查看test.txt文件,你就看到那些bss段,data段,text段等信息了,但是沒有堆棧段相關信息,用objdump命令查看.o文件的反匯編后的信息,或者用gcc -S *.c,查看各個.S文件就明白了。  文章二、內存的規划種類 1)常規內(Conventional Memory)在內存分配表中占用最前面的位置,從0KB到640KB(地址000000H~109FFFFH),共占640KB的容量。因為它在內存的最前面並且在DOS可管理的內存區,我們又稱之為Low Dos Memory(低DOS內存),或稱為基本內存(Base Memory),使用此空間的程序有BIOS、DOS操作系統、外圍設備的驅動程序、中斷向量表、一些常駐的程序、空閑可用的內存空間、以及一般的應用軟件都可在此空間執行。 2)高位內存(UM)是英文Upper Memory的縮寫,是常規內存上面的一層內存(640KB~1024KB)。
3)高端內存區(HMA)是英文High Memory Area的縮寫。它是1024KB至1088KB之間的64KB內存,管為高端內存區,其地址為100000H~10FFEFH或以上,CPU在實地址模式下以Segment:OFFSET(段地址:偏移量)方式來尋址,其尋址的最大邏輯內存空間為(FFFF:FFFF),即10FFEFH。
4)EMB是英文Extended Memory Block(擴展內存塊)的縮寫,早期采用的擴充存儲器(EPM)必須遵循EMS規范(如使用EMM386.exe),后來使用的擴展存儲器(EXM)必須遵循XMS規范(如使用Himem.sys)。擴展內存是指1MB以上的內存空間,其地址是從100000H開始,連續不斷向上擴展的內存,擴展內存取決於CPU的尋址能力。
文章三、常規內存函數 申請函數:malloc(),farmalloc(),calloc(),farcalloc(),realloc(),farealloc() 函數名: malloc 功 能: 內存分配函數 用 法: void *malloc(unsigned size); 函數名: farmalloc 功 能: 從遠堆中分配存儲塊 用 法: void far *farmalloc(unsigned long size); 函數名: calloc 功 能: 分配主存儲器 用 法: void *calloc(size_t nelem, size_t elsize); 函數名: farcalloc 功 能: 從遠堆棧中申請空間 用 法: void far *farcalloc( unsigned long units, unsigned ling unitsz ); 函數名: realloc 功 能: 重新分配主存 用 法: void *realloc(void *ptr, unsigned newsize); 函數名: farrealloc 功 能: 調整遠堆中的分配塊 用 法: void far *farrealloc( void far *block, unsigned long newsize ); 使用函數:memcpy(),memset(),memmove(),movedata() 函數名: memcpy 功 能: 從源source中拷貝n個字節到目標destin中 用 法: void *memcpy(void *destin,void *source,unsigned n); 函數名: memset 功 能: 設置s中的所有字節為ch, s數組的大小由n給定 用 法: void *memset(void *s, char ch, unsigned n); 函數名: memmove 功 能: 移動一塊字節 用 法: void *memmove(void *destin,void *source,unsigned n); 函數名: movedata 功 能: 拷貝字節 用 法: void movedata(int segsrc, int offsrc, int segdest, int offdest, unsigned numbytes); 釋放函數:free(),farfree() 函數名: free 功 能: 釋放已分配的塊 用 法: void free(void *ptr); 函數名: farfree 功 能: 從遠堆中釋放一塊 用 法: void farfree(void); 指針操作函數:MK_FP(),FP_OFF(),FP_SEG() 函數名: MK_FP 功 能: 設置一個遠指針 用 法: void far *MK_FP(unsigned seg, unsigned off); 函數名: FP_OFF 功 能: 獲取遠地址偏移量 用 法: unsigned FP_OFF(void far *farptr); 函數名: FP_SEG 功 能: 獲取遠地址段值 用 法: unsigned FP_SEG(void far *farptr); |