国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - C/C++ - C語言編程動態內存分配常見錯誤全面分析

C語言編程動態內存分配常見錯誤全面分析

2022-02-13 15:52高郵吳少 C/C++

這篇文章主要介紹了C語言編程中動態內存分配的常見錯誤全面分析講解,同樣遇到過C語言動態內存分配各種問題的同學可以借鑒參考下,希望能夠有所幫助

前言:為什么存在動態內存分配

我們已經掌握的內存開辟方式如下

int a=10;//在棧空間上開辟4字節
char arr[10]={0};//在棧空間上開辟10字節連續空間

以上開辟空間的方法有兩個缺點:
1.空間開辟的大小是固定的。
2.數組在聲明的時候,必須指定數組長度,它所需要的內存在編譯時進行分配。
但是對于空間的需求,不僅僅是上述的情況。有時我們需要的空間大小在程序運行時才能知道,這時上述的方法就不能滿足需要了,我們來介紹一種解決方案:動態內存分配

 

一、動態內存函數

C語言編程動態內存分配常見錯誤全面分析

(圖片來自比特就業課)

計算機在使用時會有三個區:常見的有棧區――用來存放局部變量、函數形式參數;靜態區――用來存放靜態區和全局變量;最后一個堆區則是我們用來動態內存分配的,學習動態內存分配必須掌握以下4種函數:

1.malloc和free函數

malloc函數聲明:

void*malloc(size_t size);//size_t即unsigned int

該函數向內存申請一塊連續可用的空間,并返回指向這塊空間的指針。注意點如下:
1.如果開辟成功,返回一個指向開辟空間的指針
2.如果開辟失敗,返回一個NULL指針
(由于是NULL指針,所以對于malloc函數常用assert進行檢查)
3.返回值類型為void*,所以malloc函數開辟空間的類型需要使用者自己進行決定
4.如果size=0,malloc的行為取決具體編譯器

free函數聲明

void free(void*ptr);

free函數用來釋放動態開辟的空間,注意點如下:
1.如果參數ptr指向的空間不是動態開辟的,那free函數的行為是未知的
2.如果ptr是空指針,free函數什么也不做
實戰舉例:

#include<stdio.h>
#include<stdlib.h>//malloc和free函數頭文件
int main()
{
	int*p=(int*)malloc(40);//malloc出來的空間是不確定類型的,需要你自己強轉一個類型
	//這里我們把它轉換成int*,由整型指針對這塊空間進行維護
	//那這里會是4個字節看成一個元素,40個字節,可填充10個int元素
	if (p == NULL)
	{
		return -1;
	}//如果沒有返回值則說明開辟成功
	int i = 0;
	for (i = 0;i < 10;i++)
	{
		*(p + i)=i;//對開辟空間進行賦值操作
	}
	free(p);//用完之后不需要了,用free函數釋放p所指向的空間(40個字節全部釋放掉,還給操作系統)
	p = NULL;//由于p存儲的是開辟空間的地址,即使空間還給了操作形態,但p還是可以找到這塊空間,這是非常危險的,所以我們用一個空指針賦給p
	return 0;
}

2.calloc函數

calloc函數也是用來動態內存分配的,函數聲明如下

void*calloc(size_t num,size_t size)

該函數功能是為num個大小為size的元素開辟一塊空間,并且把空間的每個字節都初始化為0
它與malloc函數的區別只是在返回地址前會把申請空間里的每個字節都初始化為0

代碼如下(示例):

#include<stdio.h>
#include<stdlib.h>//calloc函數頭文件
#include<string.h>//strerror函數頭文件
#include<errno.h>//errno頭文件
int main()
{
	int*p = (int*)calloc(10, sizeof(int));//開辟10個大小為int型的空間
	if (p == NULL)//calloc函數也有可能開辟空間失敗,需要進行檢驗
	{
		printf("%s\n", strerror(errno));//errno是錯誤碼,strerror會把錯誤碼轉換成相應的錯誤信息
		return -1;
	}
	int i = 0;
	for (i = 0;i < 10;i++)
	{
		printf("%d ", *(p + i));//會打印10個0(calloc會自己初始化為0)
	}
	free(p);
	p = NULL;
	return 0;
}

3.realloc函數

realloc函數是在已有空間不夠的情況下,進行追加申請空間的函數,其聲明如下:

void*realloc(void*memblock,size_t size);

realloc函數是為了讓動態內存管理更加靈活,有時候我們發現之前申請的空間過少了,或者過大了,我們可以用realloc函數來進行增減,它的注意點如下:
1.ptr是要調整的內存地址
2.size是調整之后新的大小
3.返回值是調整后的內存起始位置
4.該函數在調整原先內存大小的基礎上,還會將原來內存的數據復制到新空間
5.realloc函數在調整內存空間存在兩種情況
關于4和5解釋如下:
假設我們現在追加1倍空間

C語言編程動態內存分配常見錯誤全面分析

第一種:如上圖,紅色是我們開辟的空間,藍色是其他程序正在使用的空間,又因為我們要開辟空間肯定是物理上連續的,我們又不能使用藍色部分,中間的空白空間又完全不夠原先空間的兩倍,那怎么辦?

C語言編程動態內存分配常見錯誤全面分析

我們會另外找一塊足夠空間的地方進行原空間兩倍的開辟,并且把原空間內數據進行復制到新空間,函數返回新空間的地址。

第二種:這種就比較簡單了,原先空間后面就足夠追加開辟一塊1倍的空間,我們直接進行開辟即可。

C語言編程動態內存分配常見錯誤全面分析

C語言編程動態內存分配常見錯誤全面分析

函數直接會返回原先空間的首地址。
當然了,realloc函數同malloc和calloc函數一樣,也有可能開辟空間失敗,所以依然需要檢驗是否返回的是空指針

#include<stdio.h>
#include<stdlib.h>//malloc和free函數頭文件
int main()
{
	int*p=(int*)malloc(40);//開辟10個int大小的空間
	int i = 0;
	for (i = 0;i < 10;i++)
	{
		*(p + i)=i;//對開辟空間進行賦值操作
	}
	int*ptr = realloc(p, 20 * sizeof(int));//注意!這里20*sizeof(int)是新的大小
	//比如我現在只有10個,我需要20個,差10個。但這里不是寫10,而是寫新的大小20
	if (ptr != NULL)
	{
		p = ptr;
	}
	for (i = 10;i < 20;i++)//對新開辟空間賦值
	{
		*(p + i) = i;
	}
	for (i = 0;i < 20;i++)
	{
		printf("%d ", *(p + i));//打印0-19
	}
	free(p);
	p = NULL;
	return 0;
}

 

二、常見錯誤

1.對NULL指針解引用

代碼如下(示例):

#include<stdio.h>
#include<stdlib.h>
int main()
{
	int*p = (int*)malloc(20);
	*p = 0;//對p這個地址解引用并賦值為0
	free(p);
	return 0;
}

malloc等等函數在開辟空間時都是有可能開辟失敗的,萬一失敗,就是返回空指針,你直接對空指針解引用并賦值肯定是有問題的

所以我們這里還是要進行指針檢驗
代碼如下(示例):

#include<stdio.h>
#include<stdlib.h>
int main()
{
	int*p = (int*)malloc(20);
	if(p==NULL)
	{
	return -1;
	//如果返回,開辟失敗結束程序,如果沒有返回則可進行下面的操作
	}
	*p = 0;//對p這個地址解引用并賦值為0
	free(p);
	return 0;
}

2.對動態開辟空間的越界訪問

代碼如下(示例):

#include<stdio.h>
#include<stdlib.h>
int main()
{
	int*p = (int*)malloc(200);//200個字節也就是50個int型
	if (p == NULL)
	{
		return -1;
	}
	int i = 0;
	for (i = 0;i < 60;i++)
	{
		*(p + i) = i;
	}
	free(p);
	p = NULL;
	return 0;
}

這個代碼乍一看上去沒有問題,但是仔細看的話就會發現端倪,malloc開辟200字節空間也就是50個int型,你for循環賦值最多循環次數也只能是50次啊,你循環60次肯定是越界訪問了,這里也是妥妥的會報錯。

3.對非動態開辟使用free函數

代碼如下(示例):

#include<stdio.h>
#include<stdlib.h>
int main()
{
	int a = 10;
	int*p = &a;
	free(p);
	p = NULL;
}

我們這里int創建了a,然后把a的地址賦給了int*類型的p,再然后free掉p。這種操作也是鐵定會報錯的,p這個局部變量是在棧上的,而free函數針對的是堆區

4.使用free釋放一塊動態內存開辟內存的一部分

代碼如下(示例):

//使用free釋放一塊動態內存開辟內存的一部分
#include<stdio.h>
#include<stdlib.h>
int main()
{
	int*p = (int*)malloc(10 * sizeof(int));
	if (p == NULL)
	{
		return -1;
	}
	//使用
	int i = 0;
	for (i = 0;i < 5;i++)
	{
		*p++ = i;
	}
	//釋放
	free(p);
	p = NULL;
}

這里的代碼有什么問題呢?我們畫一個圖就一目了然了

C語言編程動態內存分配常見錯誤全面分析

一開始p在上圖位置,然而隨著for循環,p++這個操作,p指向的位置不斷往后,一直到下圖位置

C語言編程動態內存分配常見錯誤全面分析

這時p已經不指向原先開辟空間的位置了,你這時候去用free釋放掉顯然是不合適的

5.對同一塊空間多次釋放

我們先來看2段代碼:

#include<stdio.h>
#include<stdlib.h>
int main()
{
	int*p = (int*)malloc(40);
	if (p == NULL)
	{
		return -1;
	}
	free(p);
	free(p);
}
#include<stdio.h>
#include<stdlib.h>
int main()
{
	int*p = (int*)malloc(40);
	if (p == NULL)
	{
		return -1;
	}
	free(p);
	p = NULL;
	free(p);
}

兩段代碼都是對同一塊空間多次釋放,但第一段代碼會報錯,第二段不會。
解釋如下:
第一段代碼你已經釋放掉p所指向的空間了,空間里什么也沒有了,但p仍然指向那塊空間,所以你再次釋放不屬于你的空間肯定會報錯。
第二段代碼你釋放掉p所指向空間,然后用空指針給p賦值,再去釋放空指針,我們知道,free空指針是什么也不做,所以不會報錯。

6.動態開辟內存忘記釋放

對于動態開辟內存忘記釋放,在堆區上申請的空間有2種回收方式:
1.你自己free掉
2.程序退出時,系統自動回收
我們先來看一段代碼

#include<stdio.h>
#include<stdlib.h>
int main()
{
	int*p = (int*)malloc(40);
	if (p == NULL)
	{
		return -1;
	}
	getchar();
	return 0;
}

該代碼我們沒有自己使用free來釋放內存,而中間又有getchar一直在等待接收字符,打個比方:假如你中途去上廁所或者干其他事情了,getchar一直沒有接收到字符,程序就一直沒有結束,那我們用p開辟的空間在你上廁所期間就一直被占用,那塊空間系統沒辦法去做別的有意義的事情。而上升到將來公司層面:我們寫的程序可能一天24h都在跑,那遇到這種情況,你沒有free掉內存,你不用又不回收,整體效率的影響是非常大的。

 

總結

今天介紹了動態內存分配函數和一些常見的動態內存分配的錯誤,希望讀者學習有所收獲,祝讀者學業有成,萬事順心!

更多關于C語言動態內存分配的資料請關注服務器之家其它相關文章!

原文鏈接:https://blog.csdn.net/m0_57180439/article/details/120515390

延伸 · 閱讀

精彩推薦
  • C/C++C語言實現電腦關機程序

    C語言實現電腦關機程序

    這篇文章主要為大家詳細介紹了C語言實現電腦關機程序,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    xiaocaidayong8482021-08-20
  • C/C++學習C++編程的必備軟件

    學習C++編程的必備軟件

    本文給大家分享的是作者在學習使用C++進行編程的時候所用到的一些常用的軟件,這里推薦給大家...

    謝恩銘10102021-05-08
  • C/C++C語言中炫酷的文件操作實例詳解

    C語言中炫酷的文件操作實例詳解

    內存中的數據都是暫時的,當程序結束時,它們都將丟失,為了永久性的保存大量的數據,C語言提供了對文件的操作,這篇文章主要給大家介紹了關于C語言中文件...

    針眼_6702022-01-24
  • C/C++深入理解goto語句的替代實現方式分析

    深入理解goto語句的替代實現方式分析

    本篇文章是對goto語句的替代實現方式進行了詳細的分析介紹,需要的朋友參考下...

    C語言教程網7342020-12-03
  • C/C++C++之重載 重定義與重寫用法詳解

    C++之重載 重定義與重寫用法詳解

    這篇文章主要介紹了C++之重載 重定義與重寫用法詳解,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下...

    青山的青6062022-01-04
  • C/C++C/C++經典實例之模擬計算器示例代碼

    C/C++經典實例之模擬計算器示例代碼

    最近在看到的一個需求,本以為比較簡單,但花了不少時間,所以下面這篇文章主要給大家介紹了關于C/C++經典實例之模擬計算器的相關資料,文中通過示...

    jia150610152021-06-07
  • C/C++c++ 單線程實現同時監聽多個端口

    c++ 單線程實現同時監聽多個端口

    這篇文章主要介紹了c++ 單線程實現同時監聽多個端口的方法,幫助大家更好的理解和學習使用c++,感興趣的朋友可以了解下...

    源之緣11542021-10-27
  • C/C++詳解c語言中的 strcpy和strncpy字符串函數使用

    詳解c語言中的 strcpy和strncpy字符串函數使用

    strcpy 和strcnpy函數是字符串復制函數。接下來通過本文給大家介紹c語言中的strcpy和strncpy字符串函數使用,感興趣的朋友跟隨小編要求看看吧...

    spring-go5642021-07-02
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 国产婷婷色一区二区三区 | 国产精品久久久久久av公交车 | 欧美视频在线观看 | 瑟瑟视频网站 | 亚洲精品久久久久久久久久久 | 国产91精品一区二区绿帽 | 久久久精品视频网站 | 精品欧美一区二区三区久久久 | 日本在线不卡视频 | 天天爽夜夜爽夜夜爽精品视频 | 精品国产黄a∨片高清在线 91精品国产91久久久 | 91精彩视频在线观看 | 亚洲 欧美 精品 | 欧美成人免费 | 日本免费一区二区在线 | 午夜看片网站 | 亚洲精品电影在线观看 | 中文字幕第一页在线 | 亚洲日本韩国在线观看 | 影音先锋中文字幕在线观看 | 欧美日韩在线免费 | 亚洲激情在线视频 | 午夜影院啊啊啊 | 91精品久久久久久久久中文字幕 | 久久综合久久综合久久综合 | 精品国产一区二区三区av性色 | 在线一区观看 | 一区二区国产在线观看 | 久久精品成人一区二区三区蜜臀 | 亚洲精品一区二区三区蜜桃久 | 亚洲综合网站 | 中文字幕1区 | 黄色网址免费观看 | 秋霞特色aa大片 | 久久精品中文视频 | 成人免费视屏 | 影音先锋中文字幕在线观看 | 91黄色片| 在线一区视频 | 国产一区二区在线免费观看 | 日本免费在线视频 |