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

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

 更新時(shí)間:2022年02月08日 17:02:23   作者:太陽(yáng)風(fēng)暴  
這篇文章主要為大家詳細(xì)介紹了語(yǔ)言C的動(dòng)態(tài)內(nèi)存管理,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助

一、動(dòng)態(tài)內(nèi)存分配

  • (1)用malloc類(lèi)的函數(shù)分配內(nèi)存;
  • (2)用這些內(nèi)存支持應(yīng)用程序;
  • (3)用free函數(shù)釋放內(nèi)存。

內(nèi)存的簡(jiǎn)答來(lái)說(shuō)的三大操作:分配----使用----釋放

內(nèi)存管理指的是:分配— ----釋放

我們編寫(xiě)的程序代碼:使用

程序本質(zhì)上就是處理數(shù)據(jù),數(shù)據(jù)信息需要存放在內(nèi)存里,就是用二極管表示的開(kāi)斷表示二進(jìn)制數(shù),進(jìn)一步用二進(jìn)制數(shù)表示萬(wàn)物:如音樂(lè)、文字、視頻、圖片、等等各種資源。

分配–釋放:為了更好的利用和回收內(nèi)存資源,最大程度的發(fā)揮計(jì)算資源,統(tǒng)一操作系統(tǒng)來(lái)調(diào)度

動(dòng)態(tài)內(nèi)存分配其實(shí)就要談到自動(dòng)內(nèi)存分配

自動(dòng)分配:內(nèi)存其實(shí)就是我們?cè)诰幊涛募锒x的變量實(shí)際在運(yùn)行時(shí)映射的內(nèi)存,這部分變量的內(nèi)存都是由系統(tǒng)自動(dòng)管理(分配-釋放)。函數(shù)體(或者語(yǔ)句塊)內(nèi)的變量都是分布在函數(shù)  里面,運(yùn)行時(shí)就會(huì)把這個(gè)幀插入到函數(shù)運(yùn)行棧里,內(nèi)存這些都由系統(tǒng)分撥,運(yùn)行完就出棧,內(nèi)存也被操作系統(tǒng)回收,一致到主函數(shù)出棧,程序退出。

動(dòng)態(tài)分配:就是我們自己手動(dòng)申請(qǐng)操作系統(tǒng)給我們程序分配的內(nèi)存,內(nèi)存區(qū)域主要在于  上,這部分資源是我們手動(dòng)申請(qǐng)和回收的。分配到的資源是我們來(lái)操作、存放數(shù)據(jù)的地方。

實(shí)際上我們定義的變量最后也會(huì)被翻譯為地址,都是通過(guò)尋址來(lái)操作變量的值(可以去看看匯編語(yǔ)言)

#include <stdio.h>
#include <stdlib.h>
 int main(void)
{
	int*pi=(int*)malloc(sizeof(int));
	*pi=5;
	printf("*pi:%d\n",*pi);
	free(pi);
 	return 0;
}

在這里插入圖片描述

注意點(diǎn)

int *pi=(int)malloc((4));

  • 然而,依賴(lài)于系統(tǒng)所用的內(nèi)存模型,整數(shù)的長(zhǎng)度可能會(huì)發(fā)生變化??梢浦驳姆椒ㄊ鞘褂胹izeof操作符,這樣不管程序在哪里運(yùn)行都會(huì)返回正確的長(zhǎng)度。
  • 使用(int)malloc(number * (sizeof(int)));*

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

有幾個(gè)內(nèi)存分配函數(shù)可以用來(lái)管理動(dòng)態(tài)內(nèi)存,雖然具體可用的函數(shù)取決于系統(tǒng),但大部分系統(tǒng)的stdlib.h頭文件中都有如下函數(shù):

malloc()

realloc()

calloc()

函數(shù)描述
malloc從堆上分配內(nèi)存
realloc在之前分配的內(nèi)存塊的基礎(chǔ)上,將內(nèi)存重新分配為更大或者更小的部分
calloc從堆上分配內(nèi)存并清零

1、malloc()

malloc函數(shù)從堆上分配一塊內(nèi)存,所分配的字節(jié)數(shù)由該函數(shù)唯一的參數(shù)指定,返回值是void指針,如果內(nèi)存不足,就會(huì)返回NULL。此函數(shù)不會(huì)清空或者修改內(nèi)存。

聲明:voidmalloc(size_t);

  • (1)從堆上分配內(nèi)存;
  • (2)內(nèi)存不會(huì)被修改或是清空;
  • (3)返回首字節(jié)的地址。

實(shí)例用法int* pi=(int*)malloc(sizeof(int));

因?yàn)楫?dāng)malloc無(wú)法分配內(nèi)存時(shí)會(huì)返回NULL,在使用它返回的指針之前先檢查NULL是不錯(cuò)的做法,如下所示:

int*pi=(int*)malloc(sizeof(int));
if(pi!=NULL)
{
	//指針沒(méi)有問(wèn)題
}else
{
	//無(wú)效的指針
}
  • (4)靜態(tài)、全局指針和malloc

初始化靜態(tài)或全局變量時(shí)不能調(diào)用函數(shù)。下面的代碼聲明一個(gè)靜態(tài)變量,并試圖用malloc來(lái)初始化:

*static int pi = malloc(sizeof(int));

這樣會(huì)產(chǎn)生一個(gè)編譯時(shí)錯(cuò)誤消息,全局變量也一樣。

對(duì)于靜態(tài)變量,可以通過(guò)在后面用一個(gè)單獨(dú)的語(yǔ)句給變量分配內(nèi)存來(lái)避免這個(gè)問(wèn)題。但是全局變量不能用單獨(dú)的賦值語(yǔ)句,因?yàn)槿肿兞渴窃诤瘮?shù)和可執(zhí)行代碼外部聲明的,賦值語(yǔ)句這類(lèi)代碼必須出現(xiàn)在函數(shù)中:

static int *pi;
pi = malloc(sizeof(int)); 

2、realloc()

聲明:void *realloc(void *ptr,size t size);

realloc函數(shù)返回指向內(nèi)存塊的指針。該函數(shù)接受兩個(gè)參數(shù),第一個(gè)參數(shù)是指向原內(nèi)存塊的指針,第二個(gè)是請(qǐng)求的大小。重新分配的塊大小和第一個(gè)參數(shù)引用的塊大小不同。返回值是指向重新分配的內(nèi)存的指針。

第一個(gè)參數(shù)第二個(gè)參數(shù)行為
無(wú)同malloc
非空0原內(nèi)存塊被釋放
非空比原內(nèi)存塊小利用當(dāng)前的塊分配更小的塊
非空比原內(nèi)存塊大要么在當(dāng)前位置要么在其他位置分配更大的塊

在這里插入圖片描述

堆管理器可以重用原始的內(nèi)存塊,且不會(huì)修改其內(nèi)容。不過(guò)程序繼續(xù)使用的內(nèi)存超過(guò)了所請(qǐng)求的8字節(jié)。也就是說(shuō),我們沒(méi)有修改字符串以便它能裝進(jìn)8字節(jié)的內(nèi)存塊中。在本例中,我們本應(yīng)該調(diào)整字符串的長(zhǎng)度以使它能裝進(jìn)重新分配的8字節(jié)。實(shí)現(xiàn)這一點(diǎn)最簡(jiǎn)單的辦法是將NUL賦給地址507。實(shí)際使用的內(nèi)存超出分配的內(nèi)存不是個(gè)好做法,應(yīng)該避免。

在這里插入圖片描述

3、calloc()

calloc函數(shù)在申請(qǐng)內(nèi)存時(shí)會(huì)清空內(nèi)存【清空內(nèi)存的意思是將其內(nèi)容置為二進(jìn)制0】

聲明: void *calloc(size_t numElements,size_t elementSize);

calloc函數(shù)會(huì)根據(jù)numElements和elementSize兩個(gè)參數(shù)的乘積來(lái)分配內(nèi)存,并返回一個(gè)指向內(nèi)存的第一個(gè)字節(jié)的指針。如果不能分配內(nèi)存,則會(huì)返回NULL。此函數(shù)最初用來(lái)輔助分配數(shù)組內(nèi)存。

如果numElements或elementSize為0,那么calloc可能返回空指針。如果calloc無(wú)法分配內(nèi)存就會(huì)返回空指針,而且全局變量errno會(huì)設(shè)置為ENOMEM(內(nèi)存不足),這是POSIX錯(cuò)誤碼,有的系統(tǒng)上可能沒(méi)有。

三、用free函數(shù)釋放內(nèi)存

有了動(dòng)態(tài)內(nèi)存分配,程序員可以將不再使用的內(nèi)存返還給系統(tǒng),這樣可以釋放內(nèi)存
留作他用。通常用free函數(shù)實(shí)現(xiàn)這一點(diǎn),該函數(shù)的原型如下:

聲明: void free(void *ptr);

指針參數(shù)應(yīng)該指向由malloc類(lèi)函數(shù)分配的內(nèi)存的地址,這塊內(nèi)存會(huì)被返還給堆。盡管指針仍然指向這塊區(qū)域,但是我們應(yīng)該將它看成指向垃圾數(shù)據(jù)。稍后可能重新分配這塊區(qū)域,并將其裝進(jìn)不同的數(shù)據(jù)。

在這里插入圖片描述

要點(diǎn)

  • 釋放含義:指的是釋放堆上的申請(qǐng)內(nèi)存,其實(shí)就是告訴堆管理器,這個(gè)資源我不用了,可以回收了
  • 本地還是保留了之前申請(qǐng)內(nèi)存的地址,這個(gè)地址我們應(yīng)該避免去使用,也就是置這個(gè)指針為NULL
  • 不能再去接引已釋放資源指針的值
  • 不能重復(fù)多次釋放指針指向的內(nèi)存(free)

四、迷途指針

如果內(nèi)存已經(jīng)釋放,而指針還在引用原始內(nèi)存,這樣的指針就稱(chēng)為迷途指針。迷途指針沒(méi)有指向有效對(duì)象,有時(shí)候也稱(chēng)為過(guò)早釋放。
迷途指針帶來(lái)的問(wèn)題:

  • 如果訪問(wèn)內(nèi)存,則行為不可預(yù)期;
  • 如果內(nèi)存不可訪問(wèn),則是段錯(cuò)誤;
  • 潛在的安全隱患。

造成的原因:

  • 訪問(wèn)已釋放的內(nèi)存;
  • 返回的指針指向的是上次函數(shù)調(diào)用中的自動(dòng)變量;
//第一種情況
int*pi = (int*)malloc(sizeof(int));
printf("*pi:%d\n",*pi);
free(pi);
*pi = 10;
 //第二種情況
int*p1 = (int*)malloc(sizeof(int));
*p1 = 5;
int* p2;
p2 = p1;
free(p1);
*p2 = 10;//迷途指針
 //第三種情況
/*
大部分編譯器都把塊語(yǔ)句當(dāng)做一個(gè)棧幀。tmp變量分配在棧幀上,之后在塊語(yǔ)句退出時(shí)會(huì)出棧。
pi指針現(xiàn)在指向一塊最終可能被其他活躍記錄(比如foo函數(shù))覆蓋的內(nèi)存區(qū)域。
圖2-13說(shuō)明的就是這種情形。
*/
int *pi;
int tmp = 5;
pi = &tmp;
//這里pi變成了迷途指針
foo();

在這里插入圖片描述

總結(jié)

本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!      

相關(guān)文章

  • QT開(kāi)發(fā)應(yīng)用程序的歡迎界面實(shí)例

    QT開(kāi)發(fā)應(yīng)用程序的歡迎界面實(shí)例

    下面小編就為大家?guī)?lái)一篇QT開(kāi)發(fā)應(yīng)用程序的歡迎界面實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-08-08
  • C++ CryptoPP使用AES實(shí)現(xiàn)加解密詳解

    C++ CryptoPP使用AES實(shí)現(xiàn)加解密詳解

    Crypto++ (CryptoPP) 是一個(gè)用于密碼學(xué)和加密的 C++ 庫(kù),提供了大量的密碼學(xué)算法和功能,這篇文章主要為大家介紹了C++ CryptoPP如何使用AES實(shí)現(xiàn)加解密,需要的可以參考下
    2023-11-11
  • C++中基本的輸入輸出函數(shù)使用指南

    C++中基本的輸入輸出函數(shù)使用指南

    這篇文章主要介紹了C++中基本的輸入輸出函數(shù)使用指南,是C++入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-09-09
  • 詳解C++實(shí)現(xiàn)鏈表的排序算法

    詳解C++實(shí)現(xiàn)鏈表的排序算法

    鏈表排序思想和數(shù)組排序類(lèi)似,區(qū)別就是數(shù)組遍歷容易,數(shù)據(jù)交換也容易;鏈表(單項(xiàng)鏈表)只能一個(gè)方向遍歷,不能逆序遍歷,且不能隨機(jī)訪問(wèn),所以排序比較麻煩。本文將詳細(xì)介紹鏈表排序的方式,并且用C++來(lái)實(shí)現(xiàn)
    2021-06-06
  • VScode上配置 c語(yǔ)言環(huán)境的圖文教程

    VScode上配置 c語(yǔ)言環(huán)境的圖文教程

    這篇文章主要介紹了配置VScode c語(yǔ)言環(huán)境,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-05-05
  • c++網(wǎng)絡(luò)編程下Linux的epoll技術(shù)和Windows下的IOCP模型

    c++網(wǎng)絡(luò)編程下Linux的epoll技術(shù)和Windows下的IOCP模型

    c++ 網(wǎng)絡(luò)編程LINUX-epoll/windows-IOCP下socket opoll函數(shù)用法 優(yōu)于select方法的epoll 以及windows下IOCP 解決多進(jìn)程服務(wù)端創(chuàng)建進(jìn)程資源浪費(fèi)問(wèn)題,感興趣的小伙伴一起來(lái)學(xué)習(xí)吧
    2021-08-08
  • C++超詳細(xì)講解標(biāo)準(zhǔn)庫(kù)

    C++超詳細(xì)講解標(biāo)準(zhǔn)庫(kù)

    C++強(qiáng)大的功能來(lái)源于其豐富的類(lèi)庫(kù)及庫(kù)函數(shù)資源。C++標(biāo)準(zhǔn)庫(kù)(C++ Standard Library, 亦可稱(chēng)作,C++標(biāo)準(zhǔn)程序庫(kù))的內(nèi)容總共在50個(gè)標(biāo)準(zhǔn)頭文件中定義。在C++開(kāi)發(fā)中,要盡可能地利用標(biāo)準(zhǔn)庫(kù)完成
    2022-06-06
  • 一文掌握scanf的用法實(shí)例小結(jié)

    一文掌握scanf的用法實(shí)例小結(jié)

    scanf的基本用法除了常規(guī)的輸入操作外還有一些特殊的用法,使用這些用法可以很方便的在輸入中讀取想要的數(shù)據(jù),這篇文章主要介紹了scanf的用法,需要的朋友可以參考下
    2023-12-12
  • Linux下semop等待信號(hào)時(shí)出現(xiàn)Interrupted System Call錯(cuò)誤(EINTR)解決方法

    Linux下semop等待信號(hào)時(shí)出現(xiàn)Interrupted System Call錯(cuò)誤(EINTR)解決方法

    本篇文章是對(duì)在Linux下semop等待信號(hào)時(shí)出現(xiàn)Interrupted System Call錯(cuò)誤(EINTR)的解決方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • C++實(shí)例講解四種類(lèi)型轉(zhuǎn)換的使用

    C++實(shí)例講解四種類(lèi)型轉(zhuǎn)換的使用

    在C++語(yǔ)言中新增了四個(gè)關(guān)鍵字static_cast、const_cast、reinterpret_cast和dynamic_cast。這四個(gè)關(guān)鍵字都是用于類(lèi)型轉(zhuǎn)換的,類(lèi)型轉(zhuǎn)換(type cast),是高級(jí)語(yǔ)言的一個(gè)基本語(yǔ)法。它被實(shí)現(xiàn)為一個(gè)特殊的運(yùn)算符,以小括號(hào)內(nèi)加上類(lèi)型名來(lái)表示,接下來(lái)讓我們一起來(lái)詳細(xì)了解
    2022-06-06

最新評(píng)論