C語言第三十四彈---動態內存管理(下)

?個人主頁:?熬夜學編程的小林

💗系列專欄:?【C語言詳解】?【數據結構詳解】

動態內存管理

1、動態內存經典筆試題分析

1.1、題目1

1.2、題目2

1.3、題目3

1.4、題目4

2、柔性數組

2.1、柔性數組的特點

2.2、柔性數組的使用

2.3、柔性數組的優勢

3、總結C/C++中程序內存區域劃分

總結


1、動態內存經典筆試題分析

1.1、題目1

void GetMemory(char *p){p = (char *)malloc(100);}
void Test(void){char *str = NULL;GetMemory(str);strcpy(str, "hello world");printf(str);}int main(){Test();return 0;}
請問運行Test 函數會有什么樣的結果?
根據C語言順序結構原則,進入Test()函數之后逐條執行,先創建一個指針變量str指向NULL,再執行GetMemory函數,將 str 傳入函數,然后動態開辟100字節空間,但是指針變量 p 出了函數會自動銷毀,然后執行strcpy函數,但是此處str 指向NULL, 程序對NULL進行解引用操作,程序崩潰 ,前面函數動態開辟內存沒有手動釋放,因此 會導致內存泄漏

1.2、題目2

char *GetMemory(void){char p[] = "hello world";return p;}
void Test(void){char *str = NULL;str = GetMemory();printf(str);}int main(){Test();return 0;}
請問運行Test 函數會有什么樣的結果?
根據C語言順序結構原則,進入Test()函數之后逐條執行,先創建一個指針變量str指向NULL,再執行GetMemory函數,將數組首元素地址作為返回值返回給str,但是此處是在棧區開辟的空間,函數結束后就會銷毀,此時str就為野指針, 打印野指針(非法訪問內存)就會出現肉眼看不懂的文字。

1.3、題目3

void GetMemory(char **p, int num){*p = (char *)malloc(num);}
void Test(void){char *str = NULL;GetMemory(&str, 100);strcpy(str, "hello");printf(str);}int main(){Test();return 0;}
請問運行Test 函數會有什么樣的結果?
根據C語言順序結構原則,進入Test()函數之后逐條執行,先創建一個指針變量str指向NULL,再執行GetMemory函數,將str的地址傳入函數,將*p開辟100個內存空間,即給str開辟100個內存空間,然后執行strcpy函數,將hello\0拷貝到str,再將str打印出來,此處沒有太大問題,唯一的問題是 str指向的空間是動態開辟的,沒有手動釋放,會導致內存泄漏。

1.4、題目4

void Test(void){char *str = (char *) malloc(100);strcpy(str, "hello");free(str);if(str != NULL){strcpy(str, "world");printf(str);}}
int main()
{Test();return 0;
}
請問運行Test 函數會有什么樣的結果?
根據C語言順序結構原則,進入Test()函數之后逐條執行,先創建一個指針變量str指向動態開辟100字節的空間,然后將該空間拷貝hello\0,然后釋放該空間(只是不能正常使用,實際還是指向該位置),此時str還是指向動態開辟的空間,因此指向strcpy函數,將world\0拷貝到str,然后打印str,即 打印出world,只是str為野指針,即非法訪問內存。

2、柔性數組

也許你從來沒有聽說過柔性數組(flexible array)這個概念,但是它確實是存在的。
C99 中, 結構中 最后?個元素 允許是 未知大小的數組 ,這就叫做『柔性數組』成員
例如:
typedef struct st_type
{int i;int a[0];//柔性數組成員
}type_a;
有些編譯器會報錯無法編譯可以改成:
typedef struct st_type
{int i;int a[];//柔性數組成員
}type_a;

2.1、柔性數組的特點

? 結構中的柔性數組成員前面必須至少?個其他成員。
? sizeof 返回的這種結構大小不包括柔性數組的內存。
? 包含柔性數組成員的結構用malloc ()函數進行內存的動態分配,并且分配的內存應該大于結構的大小,以適應柔性數組的預期大小。
例如:
typedef struct st_type
{int i;int a[0];//柔性數組成員
}type_a;
int main()
{printf("%d\n", sizeof(type_a));//輸出的是4return 0;
}

2.2、柔性數組的使用

//代碼1
#include <stdio.h>
#include <stdlib.h>
typedef struct st_type
{int i;int a[0];//柔性數組成員
}type_a;
int main()
{int i = 0;type_a *p = (type_a*)malloc(sizeof(type_a)+100*sizeof(int));//業務處理p->i = 100;for(i=0; i<100; i++){p->a[i] = i;}free(p);return 0;
}
這樣柔性數組成員a,相當于獲得了100個整型元素的連續空間。

2.3、柔性數組的優勢

上述的 type_a 結構也可以設計為下面的結構,也能完成同樣的效果
//代碼2
#include <stdio.h>
#include <stdlib.h>
typedef struct st_type
{int i;int *p_a;
}type_a;
int main()
{type_a *p = (type_a *)malloc(sizeof(type_a));p->i = 100;p->p_a = (int *)malloc(p->i*sizeof(int));//業務處理for(i=0; i<100; i++){p->p_a[i] = i;}//釋放空間free(p->p_a);p->p_a = NULL;free(p);p = NULL;return 0;
}
上述 代碼 1 和 代碼 2 可以完成同樣的功能,但是 方法 1 的實現有兩個好處:
第?個好處是:方便內存釋放
如果我們的代碼是在?個給別人用的函數中,你在里面做了?次內存分配,并把整個結構體返回給用戶。用戶調用free可以釋放結構體,但是用戶并不知道這個結構體內的成員也需要free,所以你不能指望用戶來發現這個事。所以,如果我們把結構體的內存以及其成員要的內存?次性分配好了,并返回給用戶?個結構體指針,用戶做?次free就可以把所有的內存也給釋放掉。
第?個好處是:這樣有利于訪問速度.
連續的內存有益于提高訪問速度,也有益于減少內存碎片。(其實,我個?覺得也沒多高了,反正你跑不了要用做偏移量的加法來尋址)
擴展閱讀:
C語?結構體里的數組和指針icon-default.png?t=N7T8https://coolshell.cn/articles/11377.html

3、總結C/C++中程序內存區域劃分

C/C++程序內存分配的幾個區域:
1. 棧區(stack):在執行函數時,函數內局部變量的存儲單元都可以在棧上創建,函數執行結束時這些存儲單元自動被釋放。棧內存分配運算內置于處理器的指令集中,效率很高,但是分配的內存容量有限。 棧區主要存放運行函數而分配的局部變量、函數參數、返回數據、返回地址等。
2. 堆區(heap):?般由程序員分配釋放, 若程序員不釋放,程序結束時可能由OS回收 。分配方式類似于鏈表。
3. 數據段(靜態區):(static)存放全局變量、靜態數據。程序結束后由系統釋放。
4. 代碼段:存放函數體(類成員函數和全局函數)的?進制代碼。

總結


本篇博客就結束啦,謝謝大家的觀看,如果公主少年們有好的建議可以留言喔,謝謝大家啦!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/716660.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/716660.shtml
英文地址,請注明出處:http://en.pswp.cn/news/716660.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【c++】計算樹的深度和節點數

在C語言中&#xff0c;計算給定樹的層數&#xff08;深度&#xff09;和節點總數通常需要使用遞歸方法。首先&#xff0c;我們需要定義樹的節點結構。這里假設我們處理的是一棵二叉樹&#xff0c;每個節點有兩個子節點&#xff08;左子節點和右子節點&#xff09;。 下面是一個…

5.STL源碼解析-算法、仿函數、適配器

算法 STL算法總覽 仿函數與適配器 C標準模板庫&#xff08;STL&#xff09;是C程序員的得力工具&#xff0c;提供了許多強大而高效的數據結構和算法。在STL中&#xff0c;仿函數&#xff08;Functor&#xff09;和適配器&#xff08;Adapter&#xff09;是兩個重要的概念…

C語言文件操作(fputs() 和 puts() 有兩個小區別)

fputs() 和 puts() 有兩個小區別&#xff1a; 1.puts() 只能向標準輸出流輸出&#xff0c;而 fputs() 可以向任何流輸出。 2.使用 puts() 時&#xff0c;系統會在自動在其后添加換行符&#xff1b;而使用 fputs() 時&#xff0c;系統不會自動添加換行符。 那么這是不是意味著使…

【C++精簡版回顧】17.io流,流中提供的函數

1.流含義 2.流類 3.流對象 4.流對象的函數 舉例&#xff1a; 要求&#xff1a;數據結構中經常需要對齊輸出數據&#xff0c;應該怎么做&#xff1f; 1.頭文件 #include<iomanip> 2.創建表格頭 cout << setiosflags(ios::left) << setw(8) << "姓名…

BUGKU 網站被黑

打開環境&#xff0c;什么都沒發現&#xff0c;使用蟻劍掃描一下&#xff0c;發現shell.php&#xff0c;打開 使用BP抓包&#xff0c;進行爆破 得到密碼&#xff1a;hack 進去得到flag

GEE高階應用python wxee——如何利用來自 GOES-16 和 MODIS 的數據來可視化火災隨時間的進展分析

火災進展 wxee 是專為處理氣象數據而設計的,但它對遙感數據也很有用。在本示例中,我們將了解 wxee 如何利用來自 GOES-16 和 MODIS 的數據來可視化火災隨時間的進展情況。 安裝和設定 #!pip install wxeeimport ee import wxeeee.Authenticate() wxee.Initialize(project=x…

每日一類:QLabel深入解析

QLabel是Qt中用于顯示文本或圖像的控件&#xff0c;屬于Qt Widgets模塊。它是展示靜態內容的理想選擇&#xff0c;支持富文本格式&#xff0c;使得文本可以包含不同的字體、顏色和鏈接。QLabel也可以用來顯示圖像&#xff0c;包括動態圖像。此外&#xff0c;它還支持文本和圖像…

【Java面試題】SpringBoot與Spring的區別

主要區別體現幾個方面&#xff1a; 1.操作簡便性 SpringBoot提供極其快速和簡化的操作&#xff0c;使得Spring開發者能更快速上手。它通過提供spring的運行配置&#xff0c;以及為通用spring項目提供許多非功能性特性&#xff0c;進一步簡化了開發過程。 2.框架擴展性 Spri…

算法學習——差分

在了解差分之前&#xff0c;我們首先需要知道前綴和的概念。 前綴和簡單介紹&#xff1a; 對于一個數組A&#xff0c;要求出A[0]~A[i]的和&#xff0c;我們通常的做法是遍歷一邊&#xff0c;加起來。但是要求m組這樣的和&#xff0c;我們就要花費O(mn)的時間復雜度。顯然不合…

【考研數學】湯家鳳1800題什么水平?

我覺得湯家鳳基礎武忠祥強化這個組合非常的不錯 湯家鳳老師的講課風格 湯家鳳老師的基礎課程是大家公認的講的詳細&#xff0c;并且非常照顧基礎不好的學生&#xff0c;會把基礎知識點掰開揉碎的講給大家聽&#xff0c;在上課過程中&#xff0c;還會把知識點寫在A4紙上&#…

試了下新型的360AI搜索

360AI搜索 試了下&#xff0c;感覺還是挺不錯的。 比如問這個問題&#xff1a; ERROR 1698 (28000): Access denied for user rootlocalhost 它的回答&#xff1a; 對于ERROR 1698 (28000): Access denied for user rootlocalhost的問題&#xff0c;這通常是由于MySQL密碼為…

【Javascript】設計模式之單例模式

文章目錄 1、實現單例模式2、透明的單例模式3、用代理實現單例模式4、JavaScript 中的單例模式5、惰性單例6、通用的惰性單例7、小結 定義&#xff1a; 保證一個類僅有一個實例&#xff0c;并提供一個訪問它的全局訪問點 單例模式是一種常用的模式&#xff0c;有一些對象我們往…

JavaScript 學習總結(16)—— 實用小函數總結

1.匹配正整數 // 匹配正整數 let isPositiveNum = val => {return /^[1-9]d*$/.test(val); }; console.log(isPositiveNum(9)) //true console.log(isPositiveNum(2.2)) //false 2.匹配負整數 // 匹配負整數let isNegativeNum = val => {return /^-[1-9]d*$/.test(val…

R750 install AMD MI210GPU

一、 查看服務器GPU卡信息 可以首先在服務器上check 當前GPU的詳細信息是否匹配 二、安裝 Ubuntu22.04操作系統 服務器CHECK 安裝的AMD GPU 是否被系統識別 #lspci | grep AMD 查看GPU信息 可以看到已經識別成功 三、安裝AMD GPU驅動 https://rocm.docs.amd.com/projec…

linux 根目錄下結構

/ 虛擬目錄的根的目錄&#xff0c;通常不會在這里放置文件 /bin&#xff1a;存放頻繁使用的命令,二進制文件&#xff0c;存放了很多用戶級的GNU實用工具。 /boot&#xff1a;引導目錄&#xff0c;存放引導文件&#xff0c;包含啟動Linux所需的核心文件。 /dev&#xff1a;設…

智能駕駛規劃控制理論學習05-車輛運動學規劃案例分析

目錄 案例一——Hybrid A*&#xff08;基于正向運動學&#xff09; 1、基本思想 2、 實現流程 3、啟發函數設計 4、分析擴張&#xff08;Analytic Expansions&#xff09; 5、分級規劃&#xff08;Hierarchical planning&#xff09; 案例二——State Lattice Planning&…

子矩陣的和 刷題筆記 {二維前綴和}

首先我們的目標是讓 s[i][j]表示為其左方和上方形成的矩陣所有元素的和 加上s[i-1][j]和s[i][j-1]后 s[i-1][j-1]部分重復了所以減去 最后加上a[i][j]即可完成目標 s[i][j]s[i-1][j]s[i][j-1]-s[i-1][j-1]a[i][j]; 然后看題目要求 要求x1,y1,x2,y2圍成的小正方形內的元素和…

C/C++工程師面試題(數據庫篇)

索引的優缺點 索引是一種支持快速查找特定行的數據結構&#xff0c;如果沒有索引&#xff0c;就需要遍歷整個表進行查找。用于提高數據檢索的速度和效率。 好處&#xff1a; 提高檢索速度&#xff1a; 索引可以加快數據的檢索速度&#xff0c;因為它們允許數據庫系統直接定位到…

Revit-二開之立面視圖創建FilledRegion-(3)

在上一篇博客中介紹了FilledRegion的創建方法,這種方法通常只在平面視圖中適用,在三維視圖中也是無法創建的(目前研究的是這樣的,如果有其他方法,請賜教)。 本片文章介紹一個下在立面視圖中創建FilledRegion的方法,主要操作是在立面視圖中拾取一個點,然后以該點為原點,…

YOLOv5 項目:推理代碼和參數詳細介紹(detect)

1、前言 本章將介紹yolov5項目的推理函數&#xff0c;關于yolov5的下載和配置環境&#xff0c;參考上一篇文章&#xff1a; YOLOv5 項目&#xff1a;環境配置-CSDN博客 pycharm 中打開的推理模塊如紅框中所示 pycharm將conda新建的虛擬環境導入&#xff0c;參考 &#xff1a;…