c語言-malloc動態分配與自動分配


  • 簡單說一下c語言中malloc函數的動態分配
    malloc函數在linux終端下,敲 man malloc 就可以看到手冊中malloc函數的詳細介紹。可是。。。手冊都是英文的啊!對於英文不好的我,讀起來還是挺生硬。。。
       void *malloc(size_t size);
       void free(void *ptr);
       void *calloc(size_t nmemb, size_t size);
       void *realloc(void *ptr, size_t size);
       void *reallocarray(void *ptr, size_t nmemb, size_t size);

以上這些函數呢,就是讓程序猿來手動分配程序所需要的空間大小。函數用起來簡單,重要的是理解,不然用了還是容易出錯。所以下面主要寫的是一些初步理解方面的,等到用得多了就能更有經驗了。

與自動分配空間相比有下列一些區別:

  • 時間不同
    自動分配是編譯器默認的類型(auto自動型),自動分配空間,自動回收空間。這一過程都是在編譯時,編譯器設定好的。而動態分配程序執行時,調用malloc等函數進行分配的。

  • 空間不同
    我們把c語言編譯后的應用程序在內存中的占用,按地址高低順序分為以下部分:

  1. 棧區(stack)-存放函數的參數值,局部變量的值等。
  2. 堆區(heap)-由程序猿分配釋放,若程序猿不釋放,程序結束時可能由由系統自動回收 。
  3. 全局區(static)-存放的是全局變量和靜態變量,初始化的全局變量和靜態變量在一塊區域, 未初始化的全局變量和未初始化的靜態變量在相鄰的另一塊區域。 程序結束后由系統釋放。
  4. 文字常量區-常量字符串就是放在這里的。程序結束后由系統釋放。
  5. 代碼區-存放函數體的二進制代碼。

malloc函數分配的區域就是堆區,程序猿利用malloc函數在堆區分配一個指定大小的空間。
動態分配的好處是:自由度大,想什么時候分配就什么時候分配,分配大小也自己定,不用受編譯器和系統的太多限制。堆的空間還大。
但動態分配最致命的就是:內存泄露-指程序中動態分配的堆內存由於某種原因程序未釋放或無法釋放,造成系統內存的浪費,導致程序運行速度減慢甚至系統崩潰等嚴重后果。

自由的同時帶來了麻煩!如果把自動分配比作孩子,內存空間比作生活的開銷,系統和編譯器就是父母。父母每月給孩子固定的money,省下來的money孩子自己偷偷買皮膚,沒了父母給。而動態分配自己就是父母,只能自己替自己做主,每一筆開銷都要打量着。花完之后,一個free函數,花完的錢又回來了(要是真的就好了),不free或者free錯誤直接破產。

下面來個錯誤示范

void test1(int *p,int n)
{       
        p = malloc(n);
        if(p == NULL)
                exit(1);
}       

int main()
{       
        int num = 100;
        int *p = NULL;

        test1(p,num);
        free(p);
 
        return 0;
}

結果:

結果是空,什么也沒有,也沒有報任何錯誤。多么會鑽空子的錯誤,main函數中free的p其實是main中的空指針,這兩個函數中定義的都是局部變量,有作用域限制,這很簡單的道理,但往往就會陷入這樣的陷阱。
free函數只釋放之前調用 calloc、malloc 或 realloc 所分配的內存空間,對空指針不會進行任何操作,但也不會報錯。
free后的那片空間是自由的了,任何程序都有寫入的權利。來一個野指針試試:

int main()
{
        char *p = "1";
        p = malloc(sizeof(int));
        if(p == NULL)
        {
                printf("malloc() error!\n");
                exit(1);
        }

        *p = 10;
        printf("%d %p\n",*p,p);
        free(p);             //free完p后再對*p賦值,p就成了野指針,很危險!
//free完后最好把指針設為空指針--> p = NULL;
        printf("%d %p\n",*p,p);
        *p = 1; 
        printf("%d %p\n",*p,p);

        return 0;
}

不同環境下結果可能不同,我在這打印的結果是:

10 0x5571b0f7f2a0
0 0x5571b0f7f2a0
1 0x5571b0f7f2a0

打印地址可以看出p指針在free前后指向的地址一直沒變,而free完后的空間已經不完全由此程序所支配,任何程序都可以寫入此空間。那么p就是典型的野指針,可能會篡改其他程序的信息,出現難以預料的結果,是非常危險的!
所以謹記:
* 成對使用,有一個malloc,就應該有一個free.
* 最好在同一調用層上使用這兩個函數,不要像上面的錯誤示范一樣。
* malloc分配的內存一定要初始化。free后的指針一定要設置為NULL。

以上就是初步的理解和使用。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM