網站首頁 編程語言 正文
1.C/C++內存分布
- 棧又叫堆棧,非靜態局部變量/函數參數/返回值等等,棧是向下增長的。
- 內存映射段(共享區)是高效的I/O映射方式,用于裝載一個共享的動態內存庫。用戶可使用系統接口創建共享共享內存,做進程間通信。
- 堆用于程序運行時動態內存分配,堆是可以上增長的。
- 數據段(靜態區)--存儲全局數據和靜態數據。
- 代碼段(常量區)--可執行的代碼/只讀常量。
下面看一段代碼
int globalVar = 1;
static int staticGlobalVar = 1;
void Test()
{
static int staticVar = 1;
int localVar = 1;
int num1[10] = { 1, 2, 3, 4 };
char char2[] = "abcd";
char* pChar3 = "abcd";
int* ptr1 = (int*)malloc(sizeof(int) * 4);
int* ptr2 = (int*)calloc(4, sizeof(int));
int* ptr3 = (int*)realloc(ptr2, sizeof(int) * 4);
free(ptr1);
free(ptr3);
}
//globalVar靜態區 staticGlobalVar靜態區 staticVar靜態區 localVar棧區
//num1棧區(是數組) char2棧區(是數組,首元素地址) *char2棧區(是首元素),注意:char2并不是常量字符串,"abcd"才是,而char2是將"abcd"拷貝了一份,在棧區
//pChar3棧區(是指針) *pChar3常量區(是常量字符串)
//ptr1棧區(是指針) *ptr1堆區
2.C語言中動態內存管理方式
malloc/calloc/realloc 和 free
3.C++中動態內存管理方式
new,delete
3.1 對于內置類型
new/delete和malloc/free 針對內置類型沒有任何差別,只是用法不一樣
// 申請一個10個int的數組
int* p1 = (int*)malloc(sizeof(int) * 10);
int* p2 = new int[10];// new/delete new[]/delete[]一定要匹配,否則可能會出錯
free(p1);
delete[] p2;//這里不要忘了[]
// 申請單個int對象
int* p3 = (int*)malloc(sizeof(int));
int* p4 = new int;
free(p3);
delete p4;
3.2 對于自定義類型
對于自定義類型,new和delete會開辟空間+初始化,析構+釋放空間
malloc/free只開辟空間,釋放空間
struct ListNode
{
ListNode* _next;
ListNode* _prev;
int _val;
ListNode(int val = 0): _next(nullptr), _prev(nullptr), _val(val)
cout << "ListNode(int val = 0)" << endl;
}
~ListNode()
{
cout << "~ListNode()" << endl;}
};
int main()
{
//C malloc只是開空間 free釋放空間
struct ListNode* n1 = (struct ListNode*)malloc(sizeof(struct ListNode));
free(n1);
//C++ new 針對自定義類型,開空間+構造函數初始化
//delete 針對自定義類型,析構函數清理 + 釋放空間
ListNode* n2 = new ListNode(5); // -> 相當于c語言中BuyListNode(5)
delete n2;
//申請數組
struct ListNode* arr3 = (struct ListNode*)malloc(sizeof(struct ListNode)*4);
free(arr3);
ListNode* arr4 = new ListNode[4]{1,2,3,4};//數組初始化可以用{}
delete[] arr4;
//那么,new內置類型的時候也可以進行初始化
//int* p1 = new int(0);
//int* p2 = new int[4]{ 1, 2, 3, 4 };
}
3.3 new的底層原理
new = operator new(庫函數) + 構造函數
operator new = malloc + 失敗拋異常機制
其實operator new和malloc用法是完全一樣的,功能都是在堆上申請釋放空間,只是失敗了處理方式不一樣,malloc失敗返回NULL,operator new失敗以后拋異常
4. 常見的面試題
- (1)malloc和new的區別
相同點:都是從堆上申請空間,并且需要用戶手動釋放。
區別:
- malloc和free是函數,new和delete是操作符
- malloc申請的空間不會初始化,new可以初始化
- malloc申請空間時,需要手動計算空間大小并傳遞,new只需在其后跟上空間的類型即可
- malloc的返回值為void*, 在使用時必須強轉,new不需要,因為new后跟的是空間的類型
- malloc申請空間失敗時,返回的是NULL,因此使用時必須判空,new不需要,但是new需要捕獲異常
- 申請自定義類型對象時,malloc / free只會開辟空間,不會調用構造函數與析構函數,而new在申請空間后會調用構造函數完成對象的初始化,delete在釋放空間前會調用析構函數完成空間中資源的清理
- (2)malloc/new最大能申請多大的空間?如何malloc出4G的空間?
32位下面,最多2G左右; 在64位下面申請
- (3)內存泄漏
1)什么是內存泄漏,內存泄漏的危害?
- 什么是內存泄漏:內存泄漏指因為疏忽或錯誤造成程序未能釋放已經不再使用的內存的情況。內存泄漏并不 是指內存在物理上的消失,而是應用程序分配某段內存后,因為設計錯誤,失去了對該段內存的控制,因而 造成了內存的浪費。
- 內存泄漏的危害:長期運行的程序出現內存泄漏,影響很大,如操作系統、后臺服務等等,出現內存泄漏會導致響應越來越慢,最終卡死。
2)如何避免內存泄漏
- 工程前期良好的設計規范,養成良好的編碼規范,申請的內存空間記著匹配的去釋放。ps:這個理想狀態。但是如果碰上異常時,就算注意釋放了,還是可能會出問題。需要下一條智能指針來管理才有保證。
- 采用RAII思想或者智能指針來管理資源。
- 有些公司內部規范使用內部實現的私有內存管理庫。這套庫自帶內存泄漏檢測的功能選項。
- 出問題了使用內存泄漏工具檢測。ps:不過很多工具都不夠靠譜,或者收費昂貴。
總結一下 : 內存泄漏非常常見,解決方案分為兩種:
1 、事前預防型。如智能指針等。
2 、事后查錯型。如泄漏檢測工具。
原文鏈接:https://blog.csdn.net/m0_60416282/article/details/125543284?spm=1001.2014.3001.5502
相關推薦
- 2022-09-27 Golang?Mutex互斥鎖深入理解_Golang
- 2023-02-15 React?中使用?react-i18next?國際化的過程(react-i18next?的基本用法
- 2022-11-13 pandas進階教程之Dataframe的apply方法_python
- 2022-06-25 Python實現漸變色的水平堆疊圖_python
- 2022-10-21 Golang驗證器之validator是使用詳解_Golang
- 2022-12-27 C語言中strcpy()函數的具體實現及注意事項_C 語言
- 2023-02-18 React錯誤的習慣用法分析詳解_React
- 2022-06-07 Docker的四種網絡模式_docker
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支