成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Go 切片導致內存泄露,被坑兩次了!

開發(fā) 架構
在業(yè)務代碼的編寫上,我們經常會接受來自外部的接口數據,再把他插入到對應的數據結構中去,再進行下一步的業(yè)務聚合、裁剪、封裝、處理。

[[427414]]

本文轉載自微信公眾號「腦子進煎魚了」,作者陳煎魚。轉載本文請聯(lián)系腦子進煎魚了公眾號。

大家好,我是煎魚。

前段時間在我的 Go 讀者群里,有小伙伴們在糾結切片(slice)的問題,我寫了這篇《Go 切片這道題,吵了一個下午!》,引起了一撥各種討論,還是比較欣慰的。

這不,有小伙伴給我提出了新的題材:

來自讀者微信提問

提出的是 Go 中很容易踩坑的切片內存泄露問題。作為寵粉的煎魚肯定不會放過,爭取讓大家都避開這個 “坑”。

今天這篇文章,就由煎魚帶大家來了解這個問題:Go 切片可能可以怎么泄露法?

切片泄露的可能

在業(yè)務代碼的編寫上,我們經常會接受來自外部的接口數據,再把他插入到對應的數據結構中去,再進行下一步的業(yè)務聚合、裁剪、封裝、處理。

像在 PHP 語言,常常會放到數組(array)中。在 Go 語言,會放到切片(slice)中。因此在 Go 的切片處理邏輯中,常常會涉及到如下類似的動作。

示例代碼如下:

  1. var a []int 
  2.  
  3. func f(b []int) []int { 
  4.  a = b[:2] 
  5.  return a 
  6.  
  7. func main() { 
  8.     ... 

仔細想想,這段程序有沒有問題,是否存在內存泄露的風險?

答案是:有的。有明確的切片內存泄露的可能性和風險。

切片底層結構

可能有些小伙伴會疑惑,怎么就有問題了,是哪里有問題?

這里就得復習一下切片的底層基本數據結構了,切片在運行時的表現是 SliceHeader 結構體,定義如下:

  1. type SliceHeader struct { 
  2.  Data uintptr 
  3.  Len  int 
  4.  Cap  int 
  • Data:指向具體的底層數組。
  • Len:代表切片的長度。
  • Cap:代表切片的容量。

要點是:切片真正存儲數據的地方,是一個數組。切片的 Data 屬性中存儲的是指向所引用的數組指針地址。

背后的原因

在上述案例中,我們有一個包全局變量 a,共有 2 個切片 a 和 b,截取了 b 的一部分賦值給了 a,兩者存在著關聯(lián)。

從程序的直面來看,截取了 b 的一部分賦值給了 a,結構似乎是如下圖:

但我們進一步打開程序底層來看,他應該是如下圖所示:

切片 a 和 b 都共享著同一個底層數組(共享內存塊),sliceB 包含全部所引用的字符。sliceA 只包含了 [:2],也就是 0 和 1 兩個索引位的字符。

那他們泄露在哪里了?

泄露的點

泄露的點,就在于雖然切片 b 已經在函數內結束了他的使命了,不再使用了。但切片 a 還在使用,切片 a 和 切片 b 引用的是同一塊底層數組(共享內存塊)。

關鍵點:切片 a 引用了底層數組中的一段。

雖然切片 a 只有底層數組中 0 和 1 兩個索引位正在被使用,其余未使用的底層數組空間毫無作用。但由于正在被引用,他們也不會被 GC,因此造成了泄露。

解決辦法

解決的辦法,就是利用切片的特性。當切片的容量空間不足時,會重新申請一個新的底層數組來存儲,讓兩者徹底分手。

示例代碼如下:

  1. var a []int 
  2. var c []int    // 第三者 
  3.  
  4. func f(b []int) []int { 
  5.  a = b[:2] 
  6.    
  7.   // 新的切片 append 導致切片擴容 
  8.  c = append(c, b[:2]...) 
  9.  fmt.Printf("a: %p\nc: %p\nb: %p\n", &a[0], &c[0], &b[0]) 
  10.    
  11.  return a 

輸出結果:

  1. a: 0xc000102060 
  2.  
  3. c: 0xc000124010 
  4.  
  5. b: 0xc000102060 

這段程序,新增了一個變量 c,他容量為 0。此時將期望的數據,追加過去。自然而然他就會遇到容量空間不足的情況,也就能實現申請新底層數據。

我們再將原本的切片置為 nil,就能成功實現兩者分手的目標了。

總結

在今天這篇文章中,我們介紹了 Go 切片的一種常見的內存泄露方式。雖然我們在日常使用的時候可能沒關注到。

主要原因還是由于切片的大多數使用場景,體量都比較小。又或是不知不覺就自己擴容了,就變成暫時性泄露了。

這依然是存在風險的,在編寫 Go 代碼時需要謹慎。畢竟這可是 Go 語言官方自己都踩過坑的 “坑”。

參考

An interesting way to leak memory with Go slices

internal/poll: avoid memory leak in Writev

slice 類型內存泄露的邏輯

 

golang slice內存泄露回收

 

責任編輯:武曉燕 來源: 腦子進煎魚了
相關推薦

2023-11-04 15:11:49

2023-03-06 07:50:19

內存回收Go

2009-08-06 08:36:58

Windows 7內存泄露系統(tǒng)崩潰

2022-10-10 11:37:14

Gomap內存

2021-05-13 16:34:20

TCP客戶端

2024-06-04 08:19:34

2013-12-18 09:36:33

Fedora 20

2021-10-21 11:29:06

勒索軟件攻擊數據泄露

2021-10-27 05:42:58

間諜軟件惡意軟件網絡攻擊

2024-10-16 08:38:37

TCP編號信息

2013-05-21 11:22:15

Google+UI設計

2021-09-09 18:12:22

內存分段式網絡

2021-01-22 05:35:19

Lvm模塊Multipath

2021-11-01 23:36:24

連續(xù)區(qū)間面試

2024-07-15 00:00:00

POST瀏覽器網絡

2023-02-08 15:32:16

云服務中斷微軟

2023-01-04 18:32:31

線上服務代碼

2021-07-26 08:08:56

TCPIP網絡協(xié)議

2021-04-30 13:32:17

TCP三次握手網絡協(xié)議

2023-10-31 08:01:48

Mybatis參數jdbcurl?
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲精品国产综合区久久久久久久 | 午夜影院在线播放 | 极品粉嫩国产48尤物在线播放 | 欧美 日韩 中文 | 国产特一级黄色片 | 国产在线视频在线观看 | 亚洲激情专区 | 精品免费| 国产午夜精品一区二区三区嫩草 | 久久精品久久久久久 | 黄视频国产 | 欧美中国少妇xxx性高请视频 | 亚洲黄色av | 久久久久久久久久久爱 | 午夜三级视频 | 亚洲精品久久久一区二区三区 | 国产一区二区三区四区hd | 伊人精品在线视频 | 自拍视频一区二区三区 | 欧美二区三区 | 涩涩鲁亚洲精品一区二区 | 成人高清在线 | 欧美色综合天天久久综合精品 | 精品福利一区二区三区 | 亚洲精品第一国产综合野 | 日本成人中文字幕在线观看 | 男人午夜视频 | 亚洲永久 | 欧美黄色片 | 91精品午夜窝窝看片 | 一区二区在线不卡 | 久久亚洲一区二区 | 成人午夜视频在线观看 | 免费一级片 | 五月婷婷导航 | 99热都是精品 | 日韩黄色小视频 | 亚洲 成人 在线 | 精品一区二区电影 | 欧美一区2区三区4区公司 | 91久久|