九色国产,午夜在线视频,新黄色网址,九九色综合,天天做夜夜做久久做狠狠,天天躁夜夜躁狠狠躁2021a,久久不卡一区二区三区

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
細(xì)談Go變量的內(nèi)存分布

我們程序中的變量大多被分配在內(nèi)存的兩個(gè)區(qū)域:statckheap

01

stack和heap



首先讓我們一起來(lái)回顧一下進(jìn)程的內(nèi)存分配:
我們寫的程序代碼跑起來(lái)后,會(huì)是一個(gè)進(jìn)程;OS會(huì)給我們的進(jìn)程分配內(nèi)存;內(nèi)存結(jié)構(gòu)大致如下:

OS給一個(gè)進(jìn)程分配的內(nèi)存空間大致可以分為:代碼區(qū)、全局?jǐn)?shù)據(jù)區(qū)、棧(stack)堆(heap)、環(huán)境變量區(qū)域以及中間空白的緩沖區(qū)六個(gè)部分。其中,數(shù)據(jù)的增長(zhǎng)路徑除棧(stack)是由高到低之外,其余的均是由低到高(可看圖中數(shù)據(jù)箭頭)。

我們思考一下,為什么棧(stack)區(qū)這么特殊和其他區(qū)域路徑相反?還有,進(jìn)程內(nèi)存中stackheap和數(shù)據(jù)結(jié)構(gòu)中的stackheap名字都相同,是有什么聯(lián)系嗎?請(qǐng)帶著問(wèn)題往下看:

1.1
進(jìn)程內(nèi)存中的stack和heap

stack : 是由程序側(cè)通過(guò)系統(tǒng)調(diào)用向操作系統(tǒng)申請(qǐng)的,由操作系統(tǒng)管理和釋放,不需要程序員手動(dòng)管理;一般用于存放線程和函數(shù)中產(chǎn)生的臨時(shí)變量。這塊區(qū)域的數(shù)據(jù)使用速度較快,不用手動(dòng)管理,省心省力。

heap:是由程序側(cè)通過(guò)系統(tǒng)調(diào)用向操作系統(tǒng)申請(qǐng)的,但是需要程序員自行管理的內(nèi)存區(qū)域,因?yàn)榇藚^(qū)域的定位是global variable,用于存放全局的變量(雖然很多編程語(yǔ)言中不這么利用);程序員需要手動(dòng)或者通過(guò)GC及時(shí)free或者delete此內(nèi)存區(qū)域中的數(shù)據(jù),但是也要注意:如果頻繁的進(jìn)行刪除和添加,會(huì)導(dǎo)致內(nèi)存碎片。

1.2
數(shù)據(jù)結(jié)構(gòu)stack和heap

我們?cè)賮?lái)看看數(shù)據(jù)結(jié)構(gòu)中的stackheap;

stack


后進(jìn)先出LIFO的數(shù)據(jù)結(jié)構(gòu)。

Heap

堆的定義:

  • 完全二叉樹(shù)

  • 每一個(gè)節(jié)點(diǎn)的值都必須大于等于(或小于等于)其子樹(shù)中每個(gè)節(jié)點(diǎn)的值

根節(jié)點(diǎn)是最大數(shù)的叫做“大頂堆”,根節(jié)點(diǎn)是最小數(shù)的叫做“小頂堆”。

heap這種數(shù)據(jù)結(jié)構(gòu)經(jīng)常利用在“如何快速定位并獲取到Top N最熱門的xxx”,通常的做法如下圖:



1.3
內(nèi)存中的stack和heap與數(shù)據(jù)結(jié)構(gòu)中的stack和heap的聯(lián)系

一句話總結(jié):進(jìn)程內(nèi)存中的棧區(qū)(stack)使用的數(shù)據(jù)結(jié)構(gòu)就是stack,內(nèi)存中的heap和數(shù)據(jù)結(jié)構(gòu)中的heap則毫無(wú)關(guān)系。

看如下C代碼:

int main() {
   int a = 3; 
   int b = 5;
   ret = add(a, b);
   printf('%d', ret);
   reuturn 0;
}

int add(int x, int y) {
   int sum = 0;
   sum = x + y;
   return sum;
}

以上代碼在棧區(qū)中的數(shù)據(jù)是這樣的:

還及得上文中提到的:“進(jìn)程內(nèi)存中只有棧區(qū)(stack)數(shù)據(jù)是由高位向低位增長(zhǎng)的,其余的均為由低位向高位增長(zhǎng)嗎?”

棧區(qū)用的數(shù)據(jù)結(jié)構(gòu)是棧,函數(shù)變量的銷毀和返回順序用逆恰好符合stack先進(jìn)后出的特點(diǎn),我覺(jué)得這是棧區(qū)(stack)逆序增長(zhǎng)很重要的一點(diǎn)。

但是,最根本的原因還是在于:歷史遺留問(wèn)題。請(qǐng)看下圖:


在當(dāng)初那個(gè)內(nèi)存空間及其短缺的年代,你認(rèn)為左圖還是右圖更適合“緩沖區(qū)”?因?yàn)?code>stack區(qū)域和heap區(qū)域大小都是動(dòng)態(tài)分配的,都有“不確定性”,很顯然,左圖發(fā)生堆棧重疊更小,且更適合內(nèi)存的充分利用。

02

Go變量的位置



我們?cè)趯慍、PHP、Java的時(shí)候,可以很容易的知道,所寫的變量所在的位置:帶new、malloc等字段的,那一定是在堆上分配了,至于后續(xù)GC怎么處理,有沒(méi)有引用繼續(xù)關(guān)聯(lián),堆有沒(méi)與釋放,程序是否存在內(nèi)存泄露…這都是后續(xù)處理的問(wèn)題了;變量的存儲(chǔ)位置是妥妥的堆上了。但是,在用Go的時(shí)候要注意,new、make等等關(guān)鍵字都不好使,Go變量的位置不是由寫程序的程序員來(lái)決定的,而是Go自行處理;所以可能你的變量是new出來(lái)的,但是,最終也不一定分配到堆上,很可能是分配在棧上。

Go把變量的位置在哪兒這件事對(duì)程序員“隱藏”了,Go自行處理;因?yàn)镚o認(rèn)為:變量的存儲(chǔ)位置,會(huì)對(duì)程序的性能有一定影響,而Go是計(jì)劃打造對(duì)性能有極致要求的程序,因而自己管了。
Go是這么管的:
首先,棧stack上的效率肯定是比堆要高的,這算是常識(shí);Go在編譯期會(huì)對(duì)每一個(gè)函數(shù)變量做判斷,如果不能夠判斷此函數(shù)中的變量在返回之后是否仍被引用到,就給把變量扔堆heap上,否則,就扔棧stack上。但是注意:如果變量非常大,還是會(huì)扔到堆heap上。

2.1
逃逸分析

我們是否有辦法知道我們寫的Go程序中變量的位置呢?
答案是有的,Go向開(kāi)發(fā)者提供了變量逃逸分析的工具

go build -gcflags '-m -l' main.go // 這里的main.go也可以是某個(gè)具體的二進(jìn)制應(yīng)用程序

下面對(duì)如下代碼進(jìn)行逃逸分析:

import (
    'fmt'
)

func main(){
    a:= 3
    b := 5
    ret := add(a, b)
    fmt.Println(ret)
}

func add(x,y int)int {
    sum := x + y
    return sum
}

分析結(jié)果:

./main.go:11:16: main ... argument does not escape
./main.go:11:16: ret escapes to heap

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開(kāi)APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
程序分text, data (initialized), bss, stack, heap幾個(gè)段 - C Language Syntax - 木瓜老C
iOS中堆和棧的使用
程序中的數(shù)據(jù)在內(nèi)存中的布局
進(jìn)程的地址空間:TEXT,DATA,BSS,HEAP,STACK
堆棧和委托堆的區(qū)別(c#)一
方法重構(gòu)與性能優(yōu)化
更多類似文章 >>
生活服務(wù)
熱點(diǎn)新聞
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服