在 Win32 DLL 專案中使用全域共享變數時,若 **未在定義處顯式初始化**,變數在進程附加時可能為 0 或隨機值,導致跨模組資料共享失效。本文以 Visual Studio .NET 2003 + Windows Server 2003 實測驗證此行為。
全域共享變數必須在定義時初始化,否則無效。
// main.c
#include <windows.h>
#include "resource.h"
__declspec(dllexport) void Test(HWND hWnd);
// 共享資料段:命名為 .SHARED,屬性 READ | WRITE | SHARED
#pragma data_seg(".SHARED")
HWND g_hSharedWnd = NULL; // ✅ 定義時初始化為 NULL
// HWND g_hSharedWnd; // ❌ 未初始化:在新進程附加時不會自動歸零
#pragma data_seg()
#pragma comment(linker, "/SECTION:.SHARED,RWS")
// DLL 進入點
BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
return TRUE;
}
__declspec(dllexport) void Test(HWND hWnd)
{
g_hSharedWnd = hWnd; // 存入共享視窗句柄
}
// 主對話框按鈕事件
void CUseDlg::OnButton1()
{
Test(GetSafeHwnd()); // 呼叫 DLL 匯出函數,傳入自身視窗句柄
}
| 定義方式 | 進程 A 呼叫 Test() | 進程 B 讀取 g_hSharedWnd | 結果 |
|---|---|---|---|
HWND g_hSharedWnd = NULL; (初始化) | 設定為 0x00120345 | 讀到 0x00120345 | ✅ 共享成功 |
HWND g_hSharedWnd; (未初始化) | 設定為 0x00120345 | 讀到 0x00000000 | ❌ 共享失敗 |
/SECTION:.SHARED,RWS 僅設定區段屬性,**不改變初始化語意**。= 0 或 = NULL)#pragma data_seg(".SHARED") 明確指定共享段名稱#pragma comment(linker, "/SECTION:.SHARED,RWS") 設定讀寫共享屬性CreateFileMapping + MapViewOfFile 替代,語意更清晰、跨語言相容性更好共享段總大小受限於 **分頁檔案大小** 及 **系統分頁大小 (通常 4KB)**。僅建議存放少量純量資料 (句柄、計數器、旗標),勿存大型緩衝區。