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

VC/GCC 編譯器共享變數區段實作差異:#pragma data_seg vs __attribute__((section))

     編輯:VC 教學

前言

跨程序共享記憶體 (如多進程計數器、Hook 共享資料) 需將變數置於**具名區段**並設定 **Read/Write/Share** 屬性。VC++ 使用 #pragma data_seg + #pragma comment(linker, "/SECTION:"),GCC 使用 __attribute__((section("name"))) + 連結器腳本。本文對比兩大編譯器完整實作細節、區段屬性設定、執行期驗證程式碼。

VC++ 6.0 / VS 實作


#include 
#include 

// 1. 告訴連結器:.shared 區段屬性為 Read/Write/Share (RWS)
#pragma comment(linker, "/SECTION:.shared,RWS")

// 2. 將後續資料導向 .shared 區段
#pragma data_seg(".shared")
int g_iShared = 0x37;  // 共享變數,所有進程映射同一實體頁面
#pragma data_seg()     // 恢復預設區段 (.data/.bss)

int main()
{
    g_iShared = 200;   // 修改共享變數
    int iLocal = 300;  // 區域變數 (棧上),各進程獨有
    printf("Shared: %d, 0x%p\n", g_iShared, &g_iShared);
    printf("Local : %d, 0x%p\n", iLocal, &iLocal);
    return 0;
}

關鍵點解析

GCC (MinGW / Linux) 實作


#include 

// GCC: 直接指定區段名稱,屬性由連結器腳本/預設決定
// 注意:ELF 共享庫/可執行檔預設不支援進程間共享區段,
// 需額外處理 (mmap MAP_SHARED / shm_open / 連結器腳本 PROVIDE)
int g_iShared __attribute__((section(".shared"))) = 0x37;
// int g_iShared = 0x37; // 普通全域變數

int main()
{
    g_iShared = 200;
    int iLocal = 300;
    printf("Shared: %d, 0x%p\n", g_iShared, &g_iShared);
    printf("Local : %d, 0x%p\n", iLocal, &iLocal);
    return 0;
}

GCC 進程間共享的現實限制

  • **Windows (MinGW)**:PE 格式支援區段屬性,可用 __attribute__((section(".shared"))) 搭配連結器選項 -Wl,--section-start=.shared=0x... 或定義檔 (.def) 設定 SECTIONS .shared READ WRITE SHARED,較繁瑣。
  • **Linux (ELF)**:**無原生進程間共享區段機制**。共享記憶體標準做法:shm_open + mmap(MAP_SHARED) 或 memfd_create,將變數放入映射區手動管理。
  • 因此 GCC 範例僅示範「指定區段」,**不保證跨進程共享**。

驗證共享效果 (Windows)

  1. 編譯上述 VC++ 程式為 SharedVar.exe。
  2. 開啟**兩個命令視窗**同時執行。
  3. 觀察 Shared 位址 (0x%p) **相同**,且一方修改另一方可見 (需同步機制如 Mutex/Interlocked)。
  4. Local 位址不同 (各自棧空間)。

同步保護 (必要)


// 多進程修改共享變數必須同步
// 方案 1: Interlocked 原子操作 (簡單計數器)
InterlockedIncrement(&g_iShared);

// 方案 2: 命名 Mutex (複雜邏輯)
HANDLE hMutex = CreateMutex(NULL, FALSE, _T("Global\\MySharedVarMutex"));
WaitForSingleObject(hMutex, INFINITE);
g_iShared = complexCalculation();
ReleaseMutex(hMutex);

對比總表

指令作用
#pragma comment(linker, "/SECTION:.shared,RWS")連結器指令:區段 .shared 具備 **R**ead、**W**rite、**S**hare (跨進程共享) 屬性。區段名不可為 .text/.data/.bss 等系統保留名。
#pragma data_seg(".shared")編譯器指令:後續全域/靜態變數放入 .shared 區段。
#pragma data_seg()恢復預設區段 (.data 初始化、.bss 未初始化)。
維度VC++ (MSVC)GCC (MinGW/Linux)
語法#pragma data_seg + #pragma comment(linker)__attribute__((section))
區段屬性設定連結器指令 /SECTION:name,RWS連結器腳本 / .def / 預設 (通常無共享屬性)
跨進程共享支援**原生支援** (PE 區段 SHARED 屬性)**無原生支援** (需 mmap/shm 手動映射)
適用場景Windows Hook、多進程計數器、共享快取ELF 區段控制 (特殊段、嵌入式)、Linux 共享記憶體需用 shm
可移植性Windows 專用跨平台 (但共享語意不同)

現代替代方案 (跨平台)

  • Boost.Interprocess:managed_shared_memory、shared_memory_object、mutex,C++ RAII 風格,Windows/Linux 通用。
  • Qt:QSharedMemory + QSystemSemaphore。
  • C++20:std::atomic_ref 配合共享記憶體映射 (仍需平台特定映射 API)。

總結

VC++ 以 #pragma data_seg + 連結器 /SECTION:RWS **原生支援**跨進程共享區段,語法簡單、效果可靠。GCC __attribute__((section)) 僅控制區段歸屬,**不提供共享屬性**,Linux 下必須改用 shm_open/mmap。跨平台專案強烈建議使用 **Boost.Interprocess** 封裝平台差異,獲得型別安全、RAII 管理、可移植的共享記憶體方案。

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