柚子快報激活碼778899分享:c語言 C/C++內存詳解
柚子快報激活碼778899分享:c語言 C/C++內存詳解
歡迎來到?破曉的歷程的 博客
??不負時光,不負己??
文章目錄
C/C++內存模型C語言動態(tài)內存管理mallocrealloccallocfree
C++動態(tài)內存申請new 操作符delete 操作符注意事項用法示例
operator new和operator delete函數(shù)內存泄露
C/C++內存模型
讓我們先來看看這段代碼:
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";
const 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);
}
你知道上面代碼中定義的變量分別存儲在內存中的哪些部分嗎? 說明一下:
棧又叫做堆棧,用來存儲非靜態(tài)局部變量、函數(shù)參數(shù)和返回值等等,棧是向下增長的。內存映射段是高效的IO映射的方式,用來裝載一個共享的動態(tài)內存庫,用戶可調用接口創(chuàng)建共享內存,用于進程間通信。堆用于存儲運行時動態(tài)內存分配,堆是向上增長的。我們使用malloc動態(tài)內存申請的空間在堆上。包括我們一會兒講到的new也是如此。數(shù)據(jù)段又叫做靜態(tài)區(qū),用于存儲全局變量和靜態(tài)數(shù)據(jù)。代碼段又叫做常量區(qū),用來存儲可執(zhí)行的代碼和只讀常量。
C語言動態(tài)內存管理
malloc、realloc、calloc 和 free 是C語言中用于動態(tài)內存管理的標準庫函數(shù),它們定義在
malloc
malloc(Memory Allocation)函數(shù)用于動態(tài)分配一塊指定大小的內存區(qū)域。其原型為:
void* malloc(size_t size);
size 參數(shù)指定了要分配的字節(jié)數(shù)。如果分配成功,返回指向分配的內存區(qū)域的指針;如果分配失敗,則返回 NULL。
使用 malloc 分配的內存區(qū)域是未初始化的,其內容是未定義的。
realloc
realloc(Re-Allocation)函數(shù)用于重新調整之前通過 malloc、calloc 或 realloc 分配的內存區(qū)域的大小。其原型為:
void* realloc(void* ptr, size_t size);
ptr 是指向要調整大小的內存區(qū)域的指針。如果 ptr 是 NULL,則 realloc 的行為類似于 malloc,分配一塊新的內存區(qū)域。size 是新的大小。如果分配成功,返回指向新內存區(qū)域的指針(可能與原指針相同,也可能不同)。如果失敗,則返回 NULL,但原內存區(qū)域不會被釋放。
calloc
calloc(Contiguous Allocation)函數(shù)也用于動態(tài)分配內存,但它還會將分配的內存區(qū)域初始化為零。其原型為:
void* calloc(size_t num, size_t size);
num 指定了要分配的元素數(shù)量。size 指定了每個元素的大?。ㄒ宰止?jié)為單位)。calloc 分配的內存總大小是 num * size。分配的內存區(qū)域會被初始化為零。如果分配成功,返回指向分配的內存區(qū)域的指針;如果失敗,則返回 NULL。
free
free 函數(shù)用于釋放之前通過 malloc、calloc 或 realloc 分配的內存區(qū)域。其原型為:
void free(void* ptr);
ptr 是指向要釋放的內存區(qū)域的指針。一旦內存被釋放,ptr 指針就成為懸垂指針(dangling pointer),不應再被使用。嘗試訪問已釋放的內存區(qū)域是未定義行為,可能導致程序崩潰或數(shù)據(jù)損壞。
總的來說,malloc、realloc、calloc 和 free 提供了在C語言中進行動態(tài)內存管理的核心功能,允許程序在運行時靈活地管理內存資源。
面試題:malloc、realloc和calloc有什么區(qū)別? malloc:動態(tài)申請空間,但不對空間進行初始化 realloc:對申請過的內存空間進行擴容處理。 calloc:申請空間的同時進行初始化處理,calloc=malloc+memset。
C++動態(tài)內存申請
C語言的動態(tài)內存申請函數(shù)對于C++依舊可以使用。但也引入了新的動態(tài)內存申請方式:new、delete。
注意:malloc、realloc和calloc屬于函數(shù),但是new和delete屬于操作符
new 操作符
new 操作符用于在堆(heap)上動態(tài)分配內存,并調用對象的構造函數(shù)(如果有的話)。其基本語法有兩種形式:
為單個對象分配內存: TypeName* pointer = new TypeName(initializer);
這里,TypeName 是要創(chuàng)建的對象類型,initializer 是傳遞給對象構造函數(shù)的參數(shù)(如果構造函數(shù)需要的話;如果構造函數(shù)沒有參數(shù)或對象類型是基本數(shù)據(jù)類型,則可以省略)。pointer 是一個指向新創(chuàng)建對象的指針。 為對象數(shù)組分配內存: TypeName* array = new TypeName[arraySize];
這里,TypeName 是數(shù)組元素的類型,arraySize 是數(shù)組中元素的數(shù)量。array 是一個指向數(shù)組第一個元素的指針。注意,對于數(shù)組,不會調用構造函數(shù)來初始化每個元素(除非元素類型是類類型且該類提供了默認構造函數(shù)),而是進行默認初始化(對于類類型,調用默認構造函數(shù);對于內置類型,不進行初始化)。
delete 操作符
delete 操作符用于釋放之前通過 new 分配的內存,并調用對象的析構函數(shù)(如果有的話)。其語法也有兩種形式,對應于 new 的兩種用法:
釋放單個對象: delete pointer;
這里,pointer 是指向之前通過 new 分配的內存的指針。使用 delete 后,pointer 變成了懸垂指針,不應再被使用。 釋放對象數(shù)組: delete[] array;
這里,array 是指向之前通過 new[] 分配的內存的指針。注意,對于數(shù)組,必須使用 delete[] 而不是 delete 來釋放內存,以確保為每個元素調用析構函數(shù)(如果元素類型是類類型的話)。
注意事項
使用 new 分配的內存必須使用 delete(或 delete[])來釋放,以避免內存泄漏。釋放內存后,指針變成懸垂指針,不應再被解引用或用于其他內存操作。對于類類型的對象,new 會自動調用構造函數(shù),delete 會自動調用析構函數(shù)。這是 new/delete 與 malloc/free 的一個重要區(qū)別。如果 new 表達式失?。ɡ纾捎趦却娌蛔悖?,它會拋出 std::bad_alloc 異常(在
用法示例
#include
using namespace std;
int main()
{
int* p1 = new int(10);//申請一個空間
int* p2 = new int[10];//申請一個數(shù)值
delete p1;//釋放一個空間
delete []p2;//釋放一個數(shù)組
}
思考一下:既然已經(jīng)有了malloc等函數(shù),為什么還要設計出new這些操作符呢?new相對于malloc有哪些優(yōu)勢呢?
當申請的空間類型為內置類型時,malloc和new的功能相同。如果內存申請失敗,malloc會返回0,而new則會選擇拋異常當申請的類型為自定義類型時,malloc和new的功能就有些差別了。接下來我們就介紹一下二者之間的差別。
讓我們先來看看這段代碼:
class A
{
public:
A()
{
_a = 1;
cout << "A()" << endl;
}
public:
int _a;
};
int main()
{
A* a1 = (A*)malloc(sizeof(A));
cout << "--------------------------------------" << endl;
A* a2 = new A;
}
運行一下,我們會發(fā)現(xiàn): 說明一下: 對于自定義類型的對象,例如類對象,new對象的同時會調用構造函數(shù)對對象進行構造,delete對象的同時會調用析構函數(shù)對對象進行析構。
operator new和operator delete函數(shù)
new和delete是用戶進行動態(tài)內存申請和釋放的操作符,operator new 和operator delete是系統(tǒng)提供的全局函數(shù),new在底層調用operator new全局函數(shù)來申請空間,delete在底層通過operator delete全局函數(shù)來釋放空間。
operator new和operator delete在用法上和malloc和free完全一樣,都會在堆上申請空間
用法如下:
int* p = (int*)operator new(sizeof(int) * 10);//申請10個int類型大小的空間
operator delete (p);//對申請的空間進行釋放
其在用法上等價于:
int* q = (int*)malloc(sizeof(int) * 10);
free(p);
盡管operator new和malloc在用法和作用上非常相似。但是仍然有不同之處?
不同之處有如下:
處理錯誤的方式不同,讓我們看看如下的代碼:
總結一下: 在申請失敗的情況下,malloc返回0,operator new拋異常。
malloc VS operator new VS new
operator new=malloc+拋異常new=operator+初始化
內存泄露
什么是內存泄露?內存泄露有什么???
什么是內存泄漏:內存泄漏指因為疏忽或錯誤造成程序未能釋放已經(jīng)不再使用的內存的情況。內存泄漏并不是指內存在物理上的消失,而是應用程序分配某段內存后,因為設計錯誤,失去了對該段內存的控制,因而造成了內存的浪費。內存泄漏的危害:長期運行的程序出現(xiàn)內存泄漏,影響很大,如操作系統(tǒng)、后臺服務等等,出現(xiàn)內存泄漏會導致響應越來越慢,最終卡死。
內存泄露的分類
C/C++程序中一般我們關心兩種方面的內存泄漏:
堆內存泄漏(Heap leak) 堆內存指的是程序執(zhí)行中依據(jù)須要分配通過malloc / calloc / realloc / new等從堆中分配的一塊內存,用完后必須通過調用相應的 free或者delete 刪掉。假設程序的設計錯誤導致這部分內存沒有被釋放,那么以后這部分空間將無法再被使用,就會產生Heap Leak。系統(tǒng)資源泄漏 指程序使用系統(tǒng)分配的資源,比方套接字、文件描述符、管道等沒有使用對應的函數(shù)釋放掉,導致系統(tǒng)資源的浪費,嚴重可導致系統(tǒng)效能減少,系統(tǒng)執(zhí)行不穩(wěn)定。
如何避免內存泄露
工程前期良好的設計規(guī)范,養(yǎng)成良好的編碼規(guī)范,申請的內存空間記著匹配的去釋放。ps: 這個理想狀態(tài)。但是如果碰上異常時,就算注意釋放了,還是可能會出問題。需要下一條智 能指針來管理才有保證。采用RAII思想或者智能指針來管理資源。有些公司內部規(guī)范使用內部實現(xiàn)的私有內存管理庫。這套庫自帶內存泄漏檢測的功能選項。出問題了使用內存泄漏工具檢測。ps:不過很多工具都不夠靠譜,或者收費昂貴。 總結一下:
內存泄漏非常常見,解決方案分為兩種:1、事前預防型。如智能指針等。2、事后查錯型。如泄 漏檢測工具。
柚子快報激活碼778899分享:c語言 C/C++內存詳解
推薦閱讀
本文內容根據(jù)網(wǎng)絡資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉載請注明,如有侵權,聯(lián)系刪除。