首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> C++ 入門

STL 分配器原碼解讀:_Obj* __STL_VOLATILE* __my_free_list 雙重指針詳解

     編輯:C++ 入門

前言:遇到的神秘聲明

閱讀 SGI STL 記憶體分配器二級分配器源碼時,會看到這一行:

_Obj* __STL_VOLATILE* __my_free_list;

乍看令人困惑:_Obj* 後緊跟 __STL_VOLATILE*?這究竟是什麼類型?本文將層層拆解。

一、宏定義還原

首先查找宏定義 (通常在 stl_config.h 或類似配置頭文件):

#define __STL_VOLATILE volatile

因此原聲明等價於:

_Obj* volatile* __my_free_list;

二、C++ 聲明讀法:從右向左

遵循「右左法則」 (Clockwise/Spiral Rule):

  1. __my_free_list 是標識符。
  2. 左邊是 * → 指針。
  3. 繼續左邊是 volatile → 指向 volatile 修飾的實體 的指針。
  4. 繼續左邊是 * → 該實體本身是 指針。
  5. 最左邊 _Obj → 基礎類型是 _Obj。

結論:__my_free_list 是一個 指向「volatile _Obj*」的指針,即 二級指針,且中間層帶有 volatile 資格。

三、為什麼需要 volatile?

在二級分配器中,__my_free_list 指向空閒鏈表陣列的某個桶頭指針。volatile 告訴編譯器:

  • 該記憶體位置的值可能被「未知因素」異步修改 (如中斷處理程式、硬體暫存器、多執行緒並發訪問)。
  • 禁止優化:每次讀寫必須真實訪問記憶體,不能缓存到暫存器、不能重排序、不能刪除「多餘」讀寫。

早期 STL 以此作為簡易執行緒同步手段 (現代 C++ 應用 std::atomic 或鎖)。

四、記憶體佈局圖解

__my_free_list (地址 A)
    │
    ▼
+-----------+     volatile _Obj* (地址 B)     +-----------+
|  指針     | ─────────────────────────────► |  指針     | ──► _Obj 節點 (地址 C)
|  (二級)   |                                  |  (一級)   |     (空閒塊頭)
+-----------+                                  +-----------+
     A                                             B
  • A:__my_free_list 變數地址 (棧上或靜態區)。
  • B:空閒鏈表桶頭指針地址 (陣列元素),類型 volatile _Obj*。
  • C:實際空閒記憶體塊鏈表頭節點地址。

五、代碼操作語義

// 取桶頭指針 (讀取 volatile 指針)
_Obj* volatile* bucket = &__my_free_list[index];
_Obj* head = *bucket; // 讀取 volatile 物件 → 強制從記憶體讀取

// 修改桶頭指針 (寫入 volatile 指針)
*bucket = new_head; // 寫入 volatile 物件 → 強制寫入記憶體,不可延遲

六、對比:硬體暫存器操作宏

文中另一個例子:

#define outp_w(addr, dat) *(volatile UINT32*)(addr) = dat

同理:將 addr 轉為 volatile UINT32*,解引用賦值。確保對硬體暫存器的寫入即時生效,不被編譯器優化掉。

七、現代 C++ 的替代方案

現代多執行緒代碼應棄用 volatile 做同步,改用:

  • std::atomic<_Obj*>:無鎖原子操作,明確記憶體序。
  • std::mutex + 普通指針:互斥鎖保護臨界區。
  • C++20 std::atomic_ref:對現有物件施加原子操作。

volatile 僅保証「不優化訪問」,不保證原子性、不保證記憶體順序、不建立 happens-before 關係,不適用於現代多核同步。

結語

_Obj* __STL_VOLATILE* __my_free_list 是「指向 volatile 一級指針的二級指針」。它反映了早期 STL 為多執行緒環境下空閒鏈表頭指針訪問所做的妥協:用 volatile 抑制編譯器優化,變相實現可見性。讀懂這類複雜聲明,是深入理解系統級 C++ 代碼的必修課。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved