C++入門(mén)(2)內(nèi)存泄露與智能指針-創(chuàng)新互聯(lián)

一、內(nèi)存泄漏是什么

首先看一個(gè)程序:

創(chuàng)新互聯(lián)2013年開(kāi)創(chuàng)至今,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目網(wǎng)站設(shè)計(jì)、做網(wǎng)站網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個(gè)夢(mèng)想脫穎而出為使命,1280元安陽(yáng)做網(wǎng)站,已為上家服務(wù),為安陽(yáng)各地企業(yè)和個(gè)人服務(wù),聯(lián)系電話:18980820575
int main() {
    int a = 1;
    int b = 2;
    vectorv2{&a, &b};
    while (!v2.empty()) {
        auto iter = v2.begin();
        delete *iter;
        v2.erase(iter);
    }
}

這個(gè)程序會(huì)報(bào)錯(cuò):free(): invalid pointer

原因:這個(gè)程序中的問(wèn)題在于,它是在使用delete刪除堆上的變量,而在這里a和b是棧上的變量,不能用delete刪除。所以這個(gè)程序會(huì)導(dǎo)致野指針錯(cuò)誤。

進(jìn)一步解釋:堆和棧是兩種不同的存儲(chǔ)空間,在 C++ 中用來(lái)存儲(chǔ)不同類(lèi)型的變量。

  • 棧上的變量是由編譯器自動(dòng)分配和釋放的,速度快,但是空間大小有限,不能動(dòng)態(tài)增長(zhǎng)。棧上的變量通常是局部變量或者是函數(shù)參數(shù)。

  • 堆上的變量是由程序員手動(dòng)分配和釋放的,速度慢,但是空間大小可以動(dòng)態(tài)增長(zhǎng)。堆上的變量通常是使用 new 關(guān)鍵字動(dòng)態(tài)分配的。

在這個(gè)程序中,vectorv2{&a, &b};這行代碼創(chuàng)建了一個(gè) vector 對(duì)象,并將棧上的變量 a 和 b 的地址存儲(chǔ)在了 vector 中。而在 while 循環(huán)中,使用了 delete *iter;這行代碼將這些地址對(duì)應(yīng)的內(nèi)存釋放,但是在棧上的變量 a 和 b 沒(méi)有被釋放,會(huì)導(dǎo)致程序崩潰。

棧上的變量在程序離開(kāi)它所在的作用域時(shí)會(huì)自動(dòng)釋放,因此程序員無(wú)需手動(dòng)釋放。而堆上的變量,需要程序員手動(dòng)釋放,否則會(huì)導(dǎo)致內(nèi)存泄漏。

正確程序:

int main() {
    vectorv2;
    v2.push_back(new int(1));
    v2.push_back(new int(2));
    while (!v2.empty()) {
        auto iter = v2.begin();
        delete *iter;
        v2.erase(iter);
    }
}
二、內(nèi)存閱讀方法

為方便調(diào)試和觀察,可以使用memory view。格式說(shuō)明:

每個(gè)“兩位數(shù)”表示一個(gè)字節(jié)空間所對(duì)應(yīng)的值,一個(gè)字節(jié)是8位的,用兩個(gè)16進(jìn)制數(shù)剛好表示出來(lái)(每個(gè)數(shù)4位)。在gpd中輸入 p &變量名 即可獲得變量所對(duì)應(yīng)的內(nèi)存地址。

三、智能指針之shared_ptr 基本用法

new delete和malloc free的區(qū)別:

  1. new會(huì)調(diào)用構(gòu)造函數(shù),malloc只會(huì)分配內(nèi)存。

  1. delete會(huì)調(diào)用對(duì)象的析構(gòu)函數(shù),而free不會(huì)調(diào)用任何函數(shù)。

智能指針(shared_ptr)

  • make_shared高效安全,從堆(動(dòng)態(tài)內(nèi)存)中初始化一個(gè)對(duì)象。相當(dāng)于new。

  • p.reset() 相當(dāng)于delete。

可以多個(gè)指針指向同一個(gè)內(nèi)存,內(nèi)部有一個(gè)計(jì)數(shù)變量,會(huì)記錄被多少指針指向。程序員無(wú)需手動(dòng)釋放他,系統(tǒng)會(huì)自動(dòng)釋放。

此時(shí):

如果我們此時(shí)調(diào)用ps1.reset()

再舉一個(gè)例子:

#include "iostream"
#includeusing namespace std;
int main() {
    shared_ptrp = make_shared(1);
    cout<< p.use_count()<< endl;//1
    p.reset();
    cout<< p.use_count()<< endl;//0
    cout<< (p == nullptr)<< endl;//true
    return 0;
}
使用陷阱
  1. 不要使用裸指針初始化多個(gè)智能指針,一個(gè)智能指針的use_count為0后會(huì)釋放內(nèi)存導(dǎo)致另一個(gè)智能指針異常。

  1. 與上一個(gè)同理不要將一個(gè)智能指針的get()綁定到另一個(gè)智能指針上,例如一下程序無(wú)法正常運(yùn)行。

int main() {
    shared_ptrp = make_shared(10);
    int *p_bare = p.get();
    {
        shared_ptrp2(p_bare);
    }
    cout<< p.use_count()<< endl;
}

解決方法:只有智能指針或make_shared初始化智能指針。只有比較古老的需要裸指針的API采用get(內(nèi)部不會(huì)釋放指針也不會(huì)用它初始化智能指針)。

四、智能指針之weak_ptr

輔助shared_ptr工作(像一個(gè)旁觀者),weak是弱,強(qiáng)指的是shared_ptr。weak_ptr也是一個(gè)類(lèi)模板,用來(lái)指向shared_ptr管理的對(duì)象但是weak_ptr這種指向不會(huì)控制所指向?qū)ο蟮纳芷凇<床粫?huì)改變shared_ptr的引用計(jì)數(shù)??梢杂糜诮鉀Q循環(huán)引用的問(wèn)題。

weak_ptr的創(chuàng)建

用shared_ptr來(lái)初始化。weak_ptrpw(ps)

常用操作 lock

檢查weak_ptr是否存在,如果存在則返回指向?qū)ο蟮膕hared_ptr否則返回一個(gè)空的shared_ptr。

intmain(){
    autosp=make_shared(100);
    // wc = 0, uc = 1
    autowp=weak_ptr(sp);
    // wc = 1, uc = 1
    autosp2=wp.lock();
    // wc = 1, uc = 2
    return0;
}
use_count、reset、expired

use_count返回強(qiáng)引用個(gè)數(shù),reset釋放,expired判斷use_count是否為0。

weak_count

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧

本文標(biāo)題:C++入門(mén)(2)內(nèi)存泄露與智能指針-創(chuàng)新互聯(lián)
轉(zhuǎn)載來(lái)源:http://muchs.cn/article20/hegco.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供移動(dòng)網(wǎng)站建設(shè)、手機(jī)網(wǎng)站建設(shè)、響應(yīng)式網(wǎng)站微信公眾號(hào)、定制網(wǎng)站、網(wǎng)頁(yè)設(shè)計(jì)公司

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

網(wǎng)站托管運(yùn)營(yíng)