C和汇编----存储类别、链接和内存管理
0x01 存儲類別
1、作用域
一個C變量的作用域可以是塊作用域、函數作用域、函數原型作用域或文件作用域。
1.1 塊作用域:
塊是用一對花括號括起來的代碼區域。比如函數體就是一個塊。定義在塊中的變量具有塊作用域,塊作用域變量的可見范圍是從定義處到包含該定義的塊的末尾
1.2 函數作用域
僅用于goto語句的標簽。一個標簽首次出現在函數的內層塊中,它的作用域也延伸至整個函數
1.3 函數原型作用域
用于函數原型中的形參名,作用范圍是從形參定義處到原型聲明結束。這意味著,編譯器在處理函數原型中的形參時只關心它的類型,而形參名通常無關緊要。
1.4文件作用域
變量的定義在函數外面,具有文件作用域,從它的定義處到該定義所在文件的末尾均可見。
2、鏈接
C變量有3種鏈接屬性:外部鏈接、內部鏈接或無鏈接。具有塊作用域、函數作用域或函數原型作用域的變量都是無鏈接變量。這意味著這些變量屬于定義他們的塊、函數或原型私有。具有文件作用域的變量可以是外部鏈接或內部鏈接。外部鏈接變量可以在多文件程序中使用,內部鏈接變量只能在一個文件中使用。當一個文件作用域變量用static修飾時就是內部鏈接
3、存儲期
C有4種存儲期:靜態存儲期、線程存儲期、自動存儲期、動態分配存儲期
- 靜態存儲期:在程序的執行期間一直存在,文件作用域具有靜態存儲期
- 線程存儲期:用于并發程序設計,程序執行可被分為多個線程。從被聲明到線程結束一直存在
- 自動存儲期:塊作用域的變量通常都具有自動存儲期,當程序進入定義這些變量的塊時,為這些變量分配內存,當退出這個塊時,釋放剛才為變量分配的內存
4、存儲類別說明符
- auto:表名變量是自動存儲期,只能用于塊作用域的變量聲明中。由于在塊中聲明的變量本身就具有自動存儲期,所以使用auto主要是為了明確表達要使用外部變量同名的局部變量的意圖。
- register 說明符也只用于塊作用域的變量,它把變量歸為寄存器存儲類別,請求最快速度訪問該變量。同時,還保護了該變量的地址不被獲取。
- static 說明符創建的對象具有靜態存儲期,載入程序時創建對象,當程序結束時對象消失。如果static 用于文件作用域聲明,作用域受限于該文件。如果 static 用于塊作用域聲明,作用域則受限于該塊。
- extern 說明符表明聲明的變量定義在別處。如果包含 extern 的聲明具有文件作用域,則引用的變量必須具有外部鏈接。如果包含 extern 的聲明具有塊作用域,則引用的變量可能具有外部鏈接或內部鏈接,這接取決于該變量的定義式聲明。
5、小結
0x02 存儲類別和函數
函數也有存儲類別,可以是外部函數(默認)或靜態函數。外部函數可以被其他文件的函數訪問,但是靜態函數只能用于其定義所在的文件。
double gamma(double); /* 該函數默認為外部函數 */ static double beta(int, int); extern double delta(double, int);在同一個程序中,其他文件中的函數可以調用gamma()和delta(),但是不能調用beta(),因為以static存儲類別說明符創建的函數屬于特定模塊私有。這樣做避免了名稱沖突的問題,由于beta()受限于它所在的文件,所以在其他文件中可以使用與之同名的函數。
通常的做法是:用 extern 關鍵字聲明定義在其他文件中的函數。這樣做是為了表明當前文件中使用的函數被定義在別處。除非使用static關鍵字,否則一般函數聲明都默認為extern。
在rand0.c文件里:
static unsigned long int next=1; unsigned int rand0(void) {next=next*1103515245+12345;return (unsigned int) (next / 65536 )%32768; }在r_drive0.c文件里
#include "stdio.h"extern unsigned int rand0(void);int main(void) {int count;for(count = 0;count<5;count++)printf("%d\n",rand0());return 0; }next是靜態內部鏈接,存儲期在程序的執行期間一直存在,作用域是rand0.c文件,其他就不可以訪問了。
unsigned int rand0(void)是外部函數,其他文件可以調用,用 extern 關鍵字聲明定義rand0.c文件里
0x03 分配內存 malloc()和free()
- malloc():接收一個參數,是所需內存的字節數,返回動態分配內存塊的首字節地址。如果 malloc()分配內存失敗,將返回空指針。malloc會找到合適的空閑內存塊,這樣的內存是匿名的,malloc()函數可用于返回指向數組的指針、指向結構的指針等,所以通常該函數的返回值會被強制轉換為匹配的類型
- free()函數的參數是之前malloc()返回的地址,該函數釋放之前malloc()分配的內存,一些操作系統在程序結束時會自動釋放動態分配的內存,但是有些系統不會。為保險起見,請使用free(),不要依賴操作系統來清理。
- malloc()和free()的原型都在stdlib.h頭文件中。
- 因為char表示1字節,malloc()的返回類型通常被定義為指向char的指針。然而,從ANSI C標準開始,C使用一個新的類型:指向void的指針,把指向 void的指針賦給任意類型的指針完全不用考慮類型匹配的問題
上面的程序是動態分配數組
反匯編:
ptd=(double )malloc(maxsizeof(double));的反匯編是:
0040102F 8B 45 F8 mov eax,dword ptr [ebp-8] 00401032 C1 E0 03 shl eax,3 00401035 50 push eax 00401036 E8 95 00 00 00 call malloc (004010d0) 0040103B 83 C4 04 add esp,4 0040103E 89 45 FC mov dword ptr [ebp-4],eax先將max的值傳給eax,左移eax三位,相當于eax乘以8,就是40,剛好是傳給malloc的參數值,然后壓棧,調用malloc函數,再把eax存入dword ptr [ebp-4]中。
free(ptd);反匯編:
先把dword ptr [ebp-4]的值傳給eax,就是40,是malloc分配內存的大小,eax入棧,調用free函數,釋放這段內存
總結
以上是生活随笔為你收集整理的C和汇编----存储类别、链接和内存管理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 远控免杀专题8---BackDoor-F
- 下一篇: 远控免杀专题9 --- Avet免杀