亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

深入了解C語言的動(dòng)態(tài)內(nèi)存管理

 更新時(shí)間:2022年07月15日 11:06:34   作者:熬夜磕代碼丶  
所謂動(dòng)態(tài)和靜態(tài)就是指內(nèi)存的分配方式。動(dòng)態(tài)內(nèi)存是指在堆上分配的內(nèi)存,而靜態(tài)內(nèi)存是指在棧上分配的內(nèi)存,本文將用5600字帶你深入了解動(dòng)態(tài)內(nèi)存管理,感興趣的可以學(xué)習(xí)一下

一、為什么會(huì)存在動(dòng)態(tài)內(nèi)存

int data=20;//在??臻g上開辟4個(gè)字節(jié)空間
char ch[5]={0};//在棧開辟5個(gè)字節(jié)連續(xù)空間

上面展示的即為我們正常開辟固定的內(nèi)存空間,它有兩個(gè)方面的特點(diǎn)

1.內(nèi)存空間所占大小是固定的,不能改變的。

2.創(chuàng)建數(shù)組時(shí),必須指明長度大小,在編譯時(shí)內(nèi)存進(jìn)行分配。

很顯然靜態(tài)分配內(nèi)存分配在一些場景,就暴露出它的弊端。如果在開發(fā)之前,我們不知道空間的需求,我們有時(shí)只有在程序運(yùn)行的時(shí)候才能知道自己所需要空間大小,這時(shí)候我們只能使用動(dòng)態(tài)分配內(nèi)存了。

二、動(dòng)態(tài)內(nèi)存函數(shù)

1.malloc和free

malloc函數(shù)的參數(shù)只有一個(gè)size_t size,向內(nèi)存申請(qǐng)一塊連續(xù)可用的空間,有幾點(diǎn)需要注意

1.如果開辟成功的話,返回指向開辟好空間的指針

2.如果開辟失敗的話,則返回NULL,因此每次開辟空間之后,都要進(jìn)行檢查

3.malloc函數(shù)未定義返回類型,一切由使用者自己使用

4.需引用stdlib.h頭文件

free函數(shù)是和malloc配套使用的,每次在堆開辟動(dòng)態(tài)空間后,程序結(jié)束之前,必須進(jìn)行空間釋放,不然會(huì)出現(xiàn)動(dòng)態(tài)空間泄露,在使用free時(shí),仍需要注意幾點(diǎn)

1.如果指針指向的空間不是動(dòng)態(tài)開辟的,不能用free進(jìn)行釋放

2.如果指針指向的是null指針,則free函數(shù)什么事都不做

3.free不能多次使用

4.需引用stdlib.h頭文件

代碼如下(示例):

#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
int main()
{
	int* src = NULL;
	src = (int*)malloc(40);//開辟40字節(jié)動(dòng)態(tài)內(nèi)存
	if (src == NULL)
	{
		printf("%s", strerror(errno));
		return 1;
	}
	free(src);//進(jìn)行動(dòng)態(tài)內(nèi)存釋放
	src = NULL;
	return 0;
}

相信有人會(huì)問,不是已經(jīng)對(duì)動(dòng)態(tài)內(nèi)存進(jìn)行釋放,為什么還要令指針等于NULL,我們調(diào)試一把。

這里我們可以發(fā)現(xiàn),雖然動(dòng)態(tài)內(nèi)存進(jìn)行free釋放,但指針仍然指向被釋放的動(dòng)態(tài)內(nèi)存的地址,如果不置空,就會(huì)造成野指針,非法訪問的問題。

2.calloc

calloc和malloc最大的區(qū)別就是,malloc只負(fù)責(zé)對(duì)內(nèi)存進(jìn)行動(dòng)態(tài)開辟,但calloc不僅開辟,還進(jìn)行初始化。

代碼如下(示例):

#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
int main()
{
	int* src = (int*)calloc(10, sizeof(int));
	if (src == NULL)
		{
	      printf("%s", strerror(errno));
	      return 1;
		}
	free(src);//進(jìn)行動(dòng)態(tài)內(nèi)存釋放
	src = NULL;
	return 0;
}

我們調(diào)試一把可以發(fā)現(xiàn),calloc在開辟空間時(shí)同時(shí)進(jìn)行了初始化。所以如何我們對(duì)申請(qǐng)的內(nèi)存空間的內(nèi)容要求初始化,那么可以很方便的使用calloc函數(shù)來完成任務(wù)。

3.realloc

當(dāng)我們一次開辟動(dòng)態(tài)內(nèi)存不夠大的時(shí)候,realloc讓動(dòng)態(tài)內(nèi)存更加的靈活。realloc幾個(gè)參數(shù):

1.第一個(gè)參數(shù)為要調(diào)整內(nèi)存的地址

2.調(diào)整后大小

3.調(diào)整后內(nèi)存的起始位置

為什么還要返回調(diào)整后內(nèi)存的地址,不是直接就開辟好了嗎?其實(shí)reallloc函數(shù)在開辟時(shí)有以下兩種情況:

1.原來的內(nèi)存之后空間是足夠的,則直接開辟

2.原來的內(nèi)存之后空間不夠用。

我們畫圖刨析一下

情況1:直接追加空間,原來數(shù)據(jù)不變

情況2:沒有足夠的空間,在堆上找一個(gè)大小合適的連續(xù)空間。所以函數(shù)返回的是一個(gè)新的內(nèi)存地址。

代碼如下(示例)

#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
int main()
{
	int* src = NULL;
	src = (int*)malloc(40);//開辟40字節(jié)動(dòng)態(tài)內(nèi)存
	if (src == NULL)
	{
		printf("%s", strerror(errno));
		return 1;
	}
	src = realloc(src, 80);
	if (src == NULL)
	{
		printf("%s", strerror(errno));
		return 1;
	}
	free(src);//進(jìn)行動(dòng)態(tài)內(nèi)存釋放
	src = NULL;
	return 0;
}

三、動(dòng)態(tài)內(nèi)存函數(shù)常見錯(cuò)誤

1.動(dòng)態(tài)內(nèi)存越界訪問

void test1()
{
	int* src = (int*)malloc(20);
	if (NULL == src)
	{
		return 1;
	}
	int i = 0;
	for (i = 0; i < 6; i++)
	{
		(*src+i)=i
	}
	free(src);
	src = NULL;
}

在這里我們malloc只開辟了20個(gè)字節(jié),但(*src+5)造成了越界訪問

2.對(duì)NULL指針進(jìn)行解引用操作

void test2()
{
	int* src = (int*)malloc(INT_MAX);//此處INT_MAX為int的最大值
	*src = 10;//如果src是NULL時(shí),無法解引用
	free(src);
	return 0;
}

這里未對(duì)開辟的動(dòng)態(tài)內(nèi)存空間進(jìn)行是否為空的判斷,當(dāng)為空時(shí),解引用就會(huì)出現(xiàn)錯(cuò)誤。

3.使用free釋放一塊動(dòng)態(tài)開辟內(nèi)存的一部分

void test3()
{
	int* src = (int*)malloc(40);
	int i=0;
	for(i=0;i<6;i++)
	{
	*(src+i)=i;
	src++;
	}
	free(src);//此時(shí)src不指向起始位置
}

因?yàn)橹羔樦赶虻牡刂钒l(fā)生變化,不在指向起始未知,進(jìn)行free釋放是非常危險(xiǎn)的。

4.對(duì)靜態(tài)內(nèi)存進(jìn)行free釋放

void test4()
{
	int a = 20;
	int* src = &a;
	free(src);
}

5.對(duì)同一內(nèi)存空間多次釋放

void test5()
{
	int* src = (int*)malloc(40);
	free(src);
	free(src);//多次釋放
}

第一個(gè)free已經(jīng)將堆空間的動(dòng)態(tài)內(nèi)存進(jìn)行釋放,此時(shí)src已經(jīng)是一個(gè)野指針,在進(jìn)行釋放是十分危險(xiǎn)的。

6.動(dòng)態(tài)開辟空間忘記釋放

void test6()
{
	int* src = (int*)malloc(40);
	if (src != NULL)
	{

	}
	while (1);
}

在開辟動(dòng)態(tài)內(nèi)存之后,一直進(jìn)行while循環(huán),為進(jìn)行free釋放,會(huì)造成內(nèi)存泄漏。

四、經(jīng)典筆試題

1.筆試1

void test(char* src)
{
	src = (char*)malloc(30);
}
int main()
{
	char* src = NULL;
	test(src);
	strcpy(src, "wo yao jin da chang");
	printf(src);
	free(src);
}

這里會(huì)輸出wo yao jin da chang 嗎?

這里很明顯,src仍然是NULL,所以無法輸出wo yao jin da chang

2.筆試2

char* test()
{
	char arr[] = "wo yao jin da chang";
	return arr;
}
int main()
{
	char* src = NULL;
	src = tset();
	printf(src);
	return 0;
}

這里會(huì)輸出wo yao jin da chang 嗎?

這里test函數(shù)確實(shí)把字符串地址傳給了src,但是字符串是局部變量,當(dāng)函數(shù)執(zhí)行完之后,就銷毀了,所以src輸出的內(nèi)容是隨機(jī)的。

3.筆試3

void test()
{
	char* src = (char*)malloc(50);
	if (src != NULL)
	{
		strcpy(src, "wo yao jin da chang");
	}
	free(src);
	if (src != NULL)
	{
		strcpy(src, "taijuanlebujinle");
		printf(src);
	}
}

這里會(huì)輸出taijuanlebujinle 嗎?

這里對(duì)動(dòng)態(tài)內(nèi)存釋放后,繼續(xù)進(jìn)行賦值,對(duì)野指針進(jìn)行了訪問是錯(cuò)誤的。

總結(jié)

看到這里大家對(duì)動(dòng)態(tài)內(nèi)存管理已經(jīng)有了一定的認(rèn)識(shí),應(yīng)該特別注意這幾點(diǎn),在進(jìn)行動(dòng)態(tài)內(nèi)存開辟之后進(jìn)行判斷是否為空,使用完后進(jìn)行free釋放,并且置空,防止動(dòng)態(tài)內(nèi)存泄露,只要記住這幾點(diǎn)基本就可以很好的使用動(dòng)態(tài)內(nèi)存了。

以上就是深入了解C語言的動(dòng)態(tài)內(nèi)存管理的詳細(xì)內(nèi)容,更多關(guān)于C語言動(dòng)態(tài)內(nèi)存管理的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C語言模擬實(shí)現(xiàn)庫函數(shù)詳解

    C語言模擬實(shí)現(xiàn)庫函數(shù)詳解

    C語言庫函數(shù)是把自定義函數(shù)放到庫里,是別人把一些常用到的函數(shù)編完放到一個(gè)文件里,供程序員使用,下面讓我們一起來詳細(xì)了解它
    2022-07-07
  • C++實(shí)現(xiàn)LeetCode(95.獨(dú)一無二的二叉搜索樹之二)

    C++實(shí)現(xiàn)LeetCode(95.獨(dú)一無二的二叉搜索樹之二)

    這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(95.獨(dú)一無二的二叉搜索樹之二),本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • C語言如何計(jì)算字符串長度

    C語言如何計(jì)算字符串長度

    這篇文章主要介紹了C語言如何計(jì)算字符串長度問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • C語言詳細(xì)分析結(jié)構(gòu)體的內(nèi)存對(duì)齊規(guī)則

    C語言詳細(xì)分析結(jié)構(gòu)體的內(nèi)存對(duì)齊規(guī)則

    C 數(shù)組允許定義可存儲(chǔ)相同類型數(shù)據(jù)項(xiàng)的變量,結(jié)構(gòu)是 C 編程中另一種用戶自定義的可用的數(shù)據(jù)類型,它允許你存儲(chǔ)不同類型的數(shù)據(jù)項(xiàng),本篇讓我們來了解C 的結(jié)構(gòu)體內(nèi)存對(duì)齊
    2022-07-07
  • C++ 學(xué)習(xí)之旅 Windows程序內(nèi)部運(yùn)行原理

    C++ 學(xué)習(xí)之旅 Windows程序內(nèi)部運(yùn)行原理

    學(xué)習(xí)C++與.net不同的是,一定要搞清楚Windows程序內(nèi)部運(yùn)行原理,因?yàn)樗婕按蠖鄶?shù)是操作系統(tǒng)的調(diào)用,而.net畢竟是在.netFrameWork上唱戲
    2012-11-11
  • C語言中順序棧和鏈棧的定義和使用詳解

    C語言中順序棧和鏈棧的定義和使用詳解

    這篇文章主要為大家詳細(xì)介紹了C語言中順序棧和鏈棧的定義和使用,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C語言有一定的幫助,感興趣的小伙伴可以了解一下
    2022-10-10
  • 如何用c++表驅(qū)動(dòng)替換if/else和switch/case語句

    如何用c++表驅(qū)動(dòng)替換if/else和switch/case語句

    本文將介紹使用表驅(qū)動(dòng)法,替換復(fù)雜的if/else和switch/case語句,想了解詳細(xì)內(nèi)容,請(qǐng)看下文
    2021-08-08
  • 深入理解雙指針的兩種用法

    深入理解雙指針的兩種用法

    本篇文章是對(duì)雙指針的兩種用法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • C++中的六個(gè)函數(shù)

    C++中的六個(gè)函數(shù)

    本文給大家介紹了C++中的六個(gè)函數(shù),非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2018-05-05
  • C++的內(nèi)聯(lián)函數(shù)你了解嗎

    C++的內(nèi)聯(lián)函數(shù)你了解嗎

    這篇文章主要為大家詳細(xì)介紹了C++的內(nèi)聯(lián)函數(shù),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03

最新評(píng)論