C語言:3分鐘看懂 malloc

2020-12-11 不會編程的程序圓

如果對你有幫助,請不吝惜你的小手給我點個讚支持下作者!關注我不迷路

初識 動態內存分配 [C語言必知必會]

動態內存分配的引入

初學數組的時候,有一個問題經常困擾著我,就是:我們可不可以自己在程序裡定義一個數組的大小而不是在函數開頭先聲明一個很大的數組,然後僅僅使用它的一小部分?

請看下面的程序:我們需要一個大小為 N ( N < 1000)的數組,我們通常這麼寫:

intmain(void){int arr[1000] = { 0 };int N = 0;int i = 0;printf("請輸入數組的大小\n");scanf("%d", &N);printf("請輸入%d個數\n", N);for (i = 0; i < N; i++)scanf("%d", &arr[i]);return0;}

每次這麼寫我都覺得自己在繞遠路,為什麼就不能直接把輸入的變量 N 當作數組的大小直接使用?比如這樣:

arr[N]

,但是很遺憾,每次編譯器都把你扼殺在程序編譯之前!

C99才可以用變量做數組定義的大小並且可以在程序中隨時聲明變量。(C99前我們需要在函數的最前面的區域對所有變量進行聲明)

如果我不想用上面那種笨笨的辦法,又沒有支持C99的編譯器,我該怎麼辦?

可以這麼做:

int* arr = (int*)malloc(sizeof(int) * N)

sizeof(int)

代表數組中每個元素的類型

N

代表數組的元素個數

所以malloc的意義是向 堆區 要了一塊

sizeof(int) * N

這麼大的空間

malloc 與 free ——好哥倆

malloc

頭文件stdlib原型void* malloc(size_t size)所以需要根據實際你需要的類型對其強制類型轉換返回值成功時,返回指向新分配內存的指針。為避免內存洩漏,必須用 free() 或 realloc() 解分配返回的指針。失敗時,返回空指針(NULL)參數:size - 要分配的字節數定義分配 size 字節的未初始化內存。若分配成功,則返回為任何擁有基礎對齊的對象類型對齊的指針。若 size 為零,則 malloc 的行為是實現定義的。例如可返回空指針。亦可返回非空指針;但不應當解引用這種指針,而且應將它傳遞給 free 以避免內存洩漏。更多關於mallochttps://zh.cppreference.com/w/c/memory/malloc

free

頭文件stdlib原型void free( void* ptr );參數:指向要解分配的內存的指針返回值:無此函數接收空指針(並對其不處理)以減少特例的數量。不管分配成功與否,分配函數返回的指針都能傳遞給 free()這是什麼意思?意思就是malloc與free成對出現,不要忘記寫free哦。定義:解分配之前由 malloc() 、 calloc() 、 aligned_alloc (C11 起) 或 realloc() 分配的空間。若 ptr 為空指針,則函數不進行操作。[1]若 ptr 的值 不等於之前從 malloc() 、 calloc() 、 realloc() 或 aligned_alloc() (C11 起) 返回的值[2],則行為未定義。若 ptr 所指代的內存區域已經被解分配[3],則行為未定義,即是說已經以ptr 為參數調用 free() 或 realloc() ,而且沒有後繼的 malloc() 、 calloc() 或 realloc() 調用以 ptr 為結果。若在 free() 返回後通過指針 ptr 訪問內存[4],則行為未定義(除非另一個分配函數恰好返回等於 ptr 的值)。更多關於freehttps://zh.cppreference.com/w/c/memory/free

free():將申請來的空間的 首地址還給「系統」,只要申請到了空間就一定要歸還

畢竟有借有還,再借不難嘛

解讀 free

注釋1:釋放空指針有何意義?

我們在聲明一個指針時,一般把它初始化為0,也就是NULL。這樣做的好處是,如果我們在後面的程序中沒有讓這個指針指向一塊具體的空間,這個指針不會是野指針,方便我們用來判斷。比如if(p != NULL)我們還知道,當malloc失敗時返回的是 NULL所以我們一開始寫上free是好習慣,因為我們不知道我們會不會用到我們聲明的指針,也不知道malloc能不能成功這時候,free空指針就是有意義的了

注釋2:molloc申請到的指針 與 free要釋放的指針保持一致

#include<stdio.h>intmain(){int* p;p = (int*)malloc(100 * 1024); p++; //改變了 p 的首地址;free(p);//free 沒有得到 malloc時 分配給p的首地址,程序崩潰return0;}

注釋3:free釋放空間後,被釋放的指針成為野指針,不能直接使用它

#include<stdio.h>intmain(){int* p;p = (int*)malloc(100 * 1024); p++;free(p); p++;//free 釋放後 p 成為了野指針,程序崩潰return0;}

注釋4:不能多次釋放同一次malloc申請的地址

#include<stdio.h>intmain(){int* p;p = (int*)malloc(100 * 1024); p++;free(p);free(p);return0;}

現在我們就可以改進我們上面的程序啦!

#include<stdlib.h>intmain(void){int i = 0;int N = 0;int* arr;printf("請輸入數組的大小\n");scanf("%d", &N);arr = (int*)malloc(sizeof(int) * N);printf("請輸入%d個數\n", N);for (i = 0; i < N; i++)scanf("%d", &arr[i]);free(arr);return0;}

什麼?不是改進嗎?怎麼行數反而變多了?

測測你能給系統分配多大空間?

#include<stdlib.h>intmain(void){void* p;int i = 0;//每次申請100M,失敗返回空指針0,退出循環while ((p = malloc(1024 * 1024 * 100)))i++;printf("最多分配%d00M內存", i);return0;}

如果忘記了free?

我們一次程序中可以申請的內存是有限的。

如果你只是平時寫簡單的程序,寫完就關閉,退出去了,這時忘記了free的話,不會對任何人造成影響,因為作業系統有清除曾使用的內存的機制

但是如果是一個持續運行的伺服器呢?堆區中所有的空間都被你申請了呢?

free的常見問題

申請了沒有free -> 長時間運行內存逐漸下降free 後再free地址變更後,直接去free

小測試:

1.對於以下的代碼段,正確的說法是:

char *p;while(1){p = malloc(1); *p = 0;}

A:最終程序會因為沒有空間了而退出B:最終程序會因為向0地址寫入而退出C:程序會一直運行下去D:程序不能被編譯

2.對於以下代碼段:

int a[] = {1, 2, 3, 4, 5};int *p = a;int *q = &a[5];printf("%d",q-p);

sizeof(int) = 4

時,以下說法正確的是:A:因為第三行的錯誤不能編譯B:因為第三行的的錯誤運行時崩潰C:輸出5D:輸出20

3.使用malloc就可以做出運行時可以隨時改變大小的數組A:√B:

後臺回覆:2020 0204查看答案哦

歡迎各位與我交流討論!

如果對你有幫助,請不吝惜你的小手給我點個讚支持下作者!關注我不迷路

相關焦點

  • C語言malloc()函數:動態分配內存空間
    頭文件:#include <stdlib.h>malloc() 函數用來動態地分配內存空間(如果你不了解動態內存分配
  • 再論c語言裡面的void類型本質和NULL
    (2) c語言就是典型的強類型語言,c語言中所有的變量都有明確的類型;因為c語言中的一個變量都要對應內存中的一段內存,編譯器需要這個變量的類型來確定這個變量佔用內存的字節數和這一段內存的解析方法。(1) 數據類型的本質就決定變量的內存佔用數,和內存的解析方法。
  • c語言中malloc申請的空間和直接定義變量申請的空間有什麼區別?
    直接定義變量與malloc定義變量的編程含義;malloc事先分配好了內存空間。在c語言中,malloc函數原型為void*malloc(unsignedintslong),其作用是在內存的動態存儲區中分配一個長度為slong的連續空間。次函數的返回值是分配區域的起始地址,如:char*p;p=malloc(64000);//空間不夠指針為null。
  • 研究了多年C語言,卻還沒有搞懂malloc和free
    前兩天看到一個筆試題,關於malloc和free的,代碼很簡單,但是很多同學卻產生的疑問。
  • C語言|用指針實現內存動態分配(malloc、calloc函數的使用)
    C語言的全局變量、靜態局部變量的存儲是在編譯時確定的,其存儲空間的實際分配在程序開始執行前完成。對於局部自動變量,在執行進入變量定義所在的複合語句時為它們分配存儲單元,這種變量的大小也是靜態確定的。一般情況下,運行中的很多存儲要求在寫程序時無法確定,因此需要一種機制,可以根據運行時的實際存儲需求分配適當的存儲區,用於存放那些在運行中才能確定數量的數據。
  • C語言提高篇_malloc,realloc和calloc的區別
    2.calloc()與malloc相似,參數sizeOfElement為申請地址的單位元素長度,numElements為元素個數,即在內存中申請numElements*sizeOfElement字節大小的連續地址空間.
  • malloc函數及用法
    C語言中不允許動態數組類型。例如:int n;scanf("%d",&n);int a[n];用變量表示長度,想對數組的大小作動態說明,這是錯誤的。但是在實際的編程中,往往會發生這種情況,即所需的內存空間取決於實際輸入的數據,而無法預先確定。對於這種問題,用數組的辦法很難解決。
  • c語言重點知識點複習資料(5)
    4)int *p;p = (int *)malloc(4);p = (int *)malloc(sizeof(int));以上兩個等價當心填空題目,malloc的返回類型是 void * 6)函數的遞歸調用一定要記得有結束的條件,並且要會算簡單的遞歸題目。
  • stm32cubeIDE移植fatfs系統讀寫sd卡項目時malloc.c報錯的解決
    malloc.c /74hc595/Src line 58 C/C++ Problem2.Description Resource Path Location Type'mem2base' undeclared here (not in a function); did you mean 'mem1base'?
  • 輕鬆學做C語言課程設計:學生通訊錄管理系統
    —— 陸遊「冬夜讀書示子聿」# 題外話C語言課程設計,對於初學者來說,主要是綜合運用C語言基礎知識,以實際項目的形式鍛鍊編程能力。從今天開始,一起輕鬆學做C語言課程設計常見項目,建議先運行代碼,再一步步理解其實現。PS:大家也可以直接留言提供一些課程設計選題,有可能根據大家的題目提供新的示例程序。
  • 程序中出現的Libc崩潰之SIGSEGV In Malloc
    _int_malloc (av=av@entry=0x7fffff3ebc40 <main_arena>, bytes=bytes@entry=4096) at malloc.c:3789,先看下代碼和現象:#include <stdlib.h>
  • 如何通過wrap malloc定位C/C++程序的內存洩漏
    Java等程式語言會自動管理內存回收,而C/C++需要顯式的釋放,有很多手段可以避免內存洩漏,比如RAII,比如智能指針(大多基於引用計數計數),比如內存池。new/delete跟malloc/free的關係new是c++的用法,比如Foo *f = new Foo,其實它分為3步。通過operator new()分配sizeof(Foo)的內存,最終通過malloc分配。
  • malloc的實現原理
    在開發c或c++時,經常需要分配內存,如今常用的分配內存函數為malloc,tcmalloc,jemalloc,其中屬於malloc使用最平常,
  • malloc、calloc、realloc的區別
    C語言跟內存分配方式<1>從靜態存儲區域分配.內存在程序編譯的時候就已經分配好,這塊內存在程序的整個運行期間都存在.例如全局變量、static變量.<3>從堆上分配,亦稱動態內存分配.程序在運行的時候用malloc或new申請任意多少的內存,程式設計師自己負責在何時用free或delete釋放內存.動態內存的生存期由用戶決定,使用非常靈活,但問題也最多.C語言跟內存申請相關的函數主要有 alloca、calloc、malloc、free、realloc等.
  • C++ new和malloc的區別
    一、new和delete    C語言提供了malloc和free兩個系統函數,完成對堆內存的申請和釋放。而C++則提供了兩個關鍵字new和delete;1.1 規則 new/delete是關鍵字,效率高於malloc和free。
  • C語言calloc的效率為何那麼高?作業系統究竟是如何分配內存的?
    在C語言程序開發中,提到動態內存分配時,基本上每個程式設計師都明白 calloc() 和 malloc() 庫函數的區別——calloc() 函數不僅分配內存,還會將分配後的內存清零,而 malloc() 函數則對分配好的內存不做任何操作。
  • 為啥美軍方禁止在嵌入式C中使用malloc()?99%的人都不知道
    在C語言程序開發中,動態內存分配允許程序在運行時向系統申請內存使用,只不過在使用完畢後,需要顯式的釋放之,這就要求程式設計師對動態分配的內存瞭然於胸。在非常重視安全(safety-critical)的嵌入式C語言程序開發中,動態內存分配廣泛被認為是禁忌。
  • malloc/free與new/delete的區別
    malloc與free是C++/C語言的標準庫函數,new/delete是C++的運算符。它們都可用於申請動態內存和釋放內存。下面來看他們的區別。一、操作對象有所不同。
  • 12個有趣的C語言面試題
    作者註:最近的編譯器會在內部檢測棧溢出的可能,所以這樣往棧裡存儲變量很難出現棧溢出。在我的gcc裡默認就是這樣,所以我不得不使用編譯命令『-fno-stack-protector』來實現上述方案。3.main()的返回類型問:下面的代碼能 編譯通過嗎?如果能,它有什麼潛在的問題嗎?
  • C語言基礎知識學習經典入門
    目錄1 本課概要... 12 C語言入口方法... 13 C語言標準輸入與輸出... 1