1. 程式人生 > >C語言之動態記憶體分配與釋放

C語言之動態記憶體分配與釋放

一,堆記憶體

1,堆記憶體特點

堆記憶體可以存放任意型別的資料,但需要自己申請與釋放。

2,堆大小

堆大小,想像中的無窮大,但實際使用中,受限於實際記憶體的大小和記憶體是否有連續性。

二,堆記憶體的申請與釋放

1,malloc函式
  • 函式宣告:·void *malloc(size_t Size)

  • 所在檔案:stdlib.h

  • 引數:size_t Size (Size表示要申請的位元組數)

  • 返回值:void * (成功則返回“指向申請空間的指標”,失敗則返回NULL)

  • 函式功能:申請Size個位元組的堆記憶體並返回記憶體空間首地址

2,calloc函式
  • 函式宣告:void *calloc(size_t nmemb,size_t size)

  • 所在檔案:stdlib.h

  • 引數:size_t nmemb size_t size(申請nmemb個大小為size的記憶體單元)

  • 返回值:void * (成功則返回“指向申請空間的指標”,失敗則返回NULL)

  • 函式功能:申請具有若干個具有固定單元大小的堆記憶體空間,自動清零

3,realloc函式
  • 函式宣告:void *realloc(void *ptr,size_t size)

  • 所在檔案:stdlib.h

  • 引數:void *ptr ,size_t size (ptr表示原有堆記憶體空間的指標,size表示擴容後的堆記憶體空間的大小,擴容後的指標可能會改變,若原堆記憶體空間“後”沒有足夠的連續堆記憶體空間提供擴容)

  • 返回值:void * (對原堆內空間進行擴容)

  • 功能:對原堆內空間進行擴容

4,free函式
  • 函式宣告:void free(void *p)

  • 所在檔案:stdlib.h

  • 引數:void *p(指向堆內申請的合法空間)

  • 返回值:void

  • 功能:釋放手動申請的堆內合法記憶體空間

示例:

#include<stdio.h>
#include<stdlib.h>

int main()
{
  short *p=malloc(100);//以位元組為單位
  if(NULL == p)
  {  
    printf("Malloc Error!\n");
    return
-1; } free(p); int }

realloc函式只能擴容而不能縮容。
realloc函式擴容之後返回的指標和指標可能不同,可能相同。因為,若在原堆記憶體空間之後有足夠大的並且是連續的空間供擴容使用,則返回的指標與原指標相同;否則,就會另找一塊足夠大的連續空間開闢“擴容後大小”的 堆記憶體空間,將原堆記憶體空間裡的值複製到新的記憶體空間並釋放掉原堆記憶體空間。最後,返回新開闢的堆記憶體空間的首地址。

三,應用(動態陣列)

#include<stdio.h>
#include<stdlib.h>

int main()
{
  int Size,newSize;
  printf("Please input Array Size:\n");
  scanf("%d",&Size);
  int *pa=(int *)malloc(Size,sizeof(int));
  if(NULL == pa)
    return -1;
  for(int I=0;i<Size;++i)
  {
    pa[i]=i;
  }

  printf("Please input Array New Size:\n");
  scanf("%d",&newSize);
  pa=(int *)realloc(newSize,sizeof(int));
  if(NULL == pa)
    return -1;
  for(int i=Size;i<newSize;++i)
  {
    pa[i]=1000;
  }

printf("Output Array!\n");
for(int I=0;i<newSize;++i)
{
  printf("%d\n",pa[i]);
}
return 0;
}

四,錯誤案例

以下三個模型,是針對堆記憶體的使用特點而設計的:

  • 自申請、自釋放

  • 返回判空

  • 配對使用

1,申請返回判空

釋放以後未置為NULL或繼續使用

char *p=(char *)malloc(100);
if(NULL == p)
{
  return -1;
}
strcpy(p,"hello");
free(p);
//p指向的空間被釋放,但p內儲存的地址仍然存在,並且變成非法空間
p=NULL;
//將p置為空(NULL),防止p所指向的空間被使用
//若僅僅釋放而不置空,則可能會出現下來的錯誤
if(NULL != p)
{
  strcpy(p,"hello");//會因為使用了非法記憶體而出錯
}
2,伺服器模型

未釋放原有空間,而重新申請新空間,造成原有空間記憶體洩漏

while(1)
{
  char *p=(char *)malloc(1000);//在堆上申請空間
  if(NULL == p)
  {
    printf("Malloc Error!\n");
    return -1;
  }
  printf("XXXXXX\n");
  printf("oooooo\n");
  p=(char *)malloc(1000);
  //之前在堆上申請的空間尚未釋放而又申請了一段新的空間,造成記憶體洩漏
  free(p);
}
3,誰申請誰釋放模型(並非絕對)

如果沒有協同的原則,則可能會造成重複釋放

  void func(char *p)
  {
    strcpy(p,"America");
    printf("%s\n",p);
    free(p);//此處違反了誰申請誰釋放的原則
  }
  int main()
  {
    char *p=(char *)malloc(100);
    if(NULL == p)
    {
      printf("Malloc Error!\n");
      return -1;
    }
    func(p);
    free(p);//main中申請的堆空間,在main函式中釋放
    return 0;
  }

相關推薦

C語言動態記憶體分配釋放

一,堆記憶體 1,堆記憶體特點 堆記憶體可以存放任意型別的資料,但需要自己申請與釋放。 2,堆大小 堆大小,想像中的無窮大,但實際使用中,受限於實際記憶體的大小和記憶體是否有連續性。 二,堆記憶體的申請與釋放 1,malloc函式

動態記憶體分配釋放(陳銳、葛麗萍 編著《跟我學資料結構》整理)

1.malloc函式 作用:在記憶體中分配一個長度為size 的連續儲存空間,返回一個指向分配空間的起始地址的指標。          如果分配失敗,則返回NULL。 原型: void *malloc(unsigned int size)

C語言動態記憶體分配小結

為什麼存在動態記憶體分配? 我們已經掌握的記憶體開闢方式有: int val = 20;//在棧空間上開闢四個位元組 char arr[10];//在棧空間上開闢10個位元組的連續空間 但是上面開闢空間的方式有兩個特點: 1.空間開闢的大小是固定的 2.陣列在申明的時

簡單的動態記憶體分配釋放

掌握動態記憶體分配方法。 程式設計輸入學生人數n及某門課成績,計算並輸出其平均分的整數部分(請用malloc和free進行動態記憶體分配)。 input: 5 90 80 70 60 50 output: 70 #include <iostream> #include <mal

C語言動態記憶體分配(malloc,realloc,calloc,free)的基本理解和區別

#include<Windows.h> #include<stdio.h> #include<malloc.h> int main() { int* p = NULL; printf("%x\n", p); p = (int*)malloc(sizeof(int)*

C語言動態記憶體管理

  C語言之動態記憶體管理 大綱: 儲存器原理 為什麼存在動態記憶體的開闢 malloc() free() calloc() realloc() 常見錯誤 例題 柔性陣列 零(上).儲存器原理 之前我們提到了計算機的儲存器,我們再來回憶一下:      我們當時說

C語言動態分配記憶體

1. malloc()函式和free()函式 首先,我們應該知道,所有的程式都必須留出足夠的記憶體空間來儲存所使用的資料,所以我們經常會預先給程式開闢好記憶體空間,然後進行操作,但其實還有一種選擇,能夠讓記憶體分配自動進行下去。 對於傳統陣列,會遇到這樣的問

C語言動態分配內存

第一個元素 sprint 擴大 for 可選 key 。。 css text 1. malloc()函數和free()函數 首先,我們應該知道。所有的程序都必須留出足夠的內存空間來存儲所使用的數據,所以我們常常會預先給程序開辟好內存空間,然後進行操作,

C++ STL中的vector的記憶體分配釋放

1.vector的記憶體增長 vector其中一個特點:記憶體空間只會增長,不會減小,援引C++ Primer:為了支援快速的隨機訪問,vector容器的元素以連續方式存放,每一個元素都緊挨著前一個元素儲存。設想一下,當vector新增一個元素時,為了滿足連續存放這個特性,都需要重新分配空間、拷

C和指標動態記憶體分配(編寫calloc函式,函式內部使用malloc函式來獲取記憶體)

1、問題 編寫calloc函式,函式內部使用malloc函式來獲取記憶體 2、程式碼實現 #include <stdio.h> #include <stdlib.h&

c++動態記憶體分配

1.先拿指標為例,搞明白指標賦值的含義。給指標賦值就相當於是改變指標的地址,就是改變指標所指向的記憶體。#include <iostream> using namespace std; int main() { int b1 = 0, b2 = 4; int

c記憶體分配釋放(malloc,realloc,calloc,free)函式內容的整理

程式例2    從這個例子可以看出calloc分配完儲存空間後將元素初始化。   #include<stdio.h>   #include<stdlib.h>   int main(void)   {   int i;   int *pn=(int

c/c++多維陣列的動態記憶體開闢釋放

c語言版本 /************************************************************************/ /* 1、使用C語言方式模擬二維陣列的

Linux C/C++ 記憶體分配釋放 [摘抄整理]

 no malloc no free no new no delete 寫了一個簡單類,執行的時候報了個錯 ,下決心好好看下記憶體相關知識 class ConstChar{ public: ConstChar(const char *data, int size)

Netty學習旅----原始碼分析記憶體分配釋放原理

static PooledHeapByteBuf newInstance(int maxCapacity) { PooledHeapByteBuf buf = RECYCLER.get(); buf.setRefCnt(1); buf.maxCapacity(m

C和指標動態記憶體分配輸入很多整數進行排序

1、問題 讀取一列整數,然後按升序排列它們,最後列印列表 2、程式碼實現 #include <stdio.h> #include <stdlib.h> /** 此函式根據

c++學習筆記 動態記憶體分配 物件、物件陣列的動態建立和釋放

宣告:註明程式碼 出處http://www.weixueyuan.net/view/6347.html 當我們需要為類物件動態分配儲存空間時,我們應該使用C++語言提供的new與new[]操作符,而不要使用C語言提供的malloc函式。 C++語言提供的new和new[

C++ 模板類動態記憶體分配

總時間限制:  1000ms   記憶體限制:  65536kB // 在此處補充你的程式碼 描述 程式填空,輸出指定結果 #include <iostream> #include <string> #includ

5.2-day02-C++/內聯/動態記憶體分配/引用/顯示型別轉換

九、 3.內聯 1)編譯器用函式的二進位制程式碼替換函式呼叫語句,減少函式呼叫的時間開銷。這種優化策略成為內聯。 2)頻繁呼叫的簡單函式適合內聯,而稀少呼叫的複雜函式不適合內聯。 3)遞迴函式無法內聯。 4)通過inline關鍵字,可以建議

c語言動態分割槽分配演算法的FirstFit和BestFit

主要參考連結: 動態分割槽分配: https://blog.csdn.net/houchaoqun_xmu/article/details/55541299 https://blog.csdn.net/cm_cyj_1116/article/details/53518790 &nbs