如何與應用程式或其他 DLL 共用自己 DLL 中的資料? Win32 DLL 映射到調用進程的地址空間中。預設情況下,每個使用 DLL 的進程都有自己的所有 DLL 全域變數和靜態變數的執行個體。如果 DLL 需要與它的由其他應用程式載入的其他執行個體共用資料,則可使用下列方法之一: 使用 data_seg 雜注建立命名資料節。 使用記憶體對應檔。請參見有關記憶體對應檔的 Win32 文檔。 以下是一個使用 data_seg 雜注的樣本: 複製代碼 #pragma data_seg (".myseg") int i = 0; char a[32]n = "hello world";#pragma data_seg() data_seg 可用於建立新的命名節(在此樣本中為 .myseg)。為清楚起見,最典型的用法是調用資料區段 .shared。然後必須在 .def 檔案中或者使用連結器選項 /SECTION:.MYSEC,RWS 為這個新的命名資料節指定正確的共用屬性。 在使用共用資料區段之前要考慮下列限制: 必須靜態初始化共用資料區段中的所有變數。在上面的樣本中,i 初始化為 0,而 a 是初始化為“hello world”的 32 個字元。 所有共用變數放在編譯 DLL 的指定資料區段中。很大的數組可產生很大的 DLL。對於所有已初始化的全域變數都是如此。 永遠不要將特定於進程的資訊儲存在共用資料區段中。大多數 Win32 資料結構或值(如 HANDLE)僅在單個進程的上下文內才真正有效。 每個進程都將擷取它自己的地址空間。永遠不要將指標儲存在共用資料區段包含的變數中,這一點很重要。指標可能在某個應用程式中完全有效,但在另一個應用程式中卻無效。 DLL 本身有可能載入到每個進程的虛擬位址空間中的不同地址。具有指向 DLL 中的函數或指向其他共用變數的指標是不安全的。 請注意,上述最後三點適用於記憶體對應檔和共用資料區段。 記憶體對應檔優於共用資料節,原因是記憶體對應檔的起始位置是已知的。開發人員通過使用距離位於共用記憶體內的所有資料中的“共用記憶體節的起始位置的位移量”,可以實作類別似於指標的行為。為使此操作快速簡便,強烈建議使用 __based 指標。但一定要記住:在每個進程中,基(或記憶體對應檔的起始位置)可能不同,因此儲存 __based 指標的基的變數自身不能位於共用記憶體中。 這些限制對 C++ 類有重要的含義。 具有虛函數的類總是包含函數指標。具有虛函數的類永遠不應儲存在共用資料區段中,也不應儲存在記憶體對應檔中。這對於 MFC 類或從 MFC 繼承的類尤其重要。 待用資料成員以全域變數的等效形式實現。這意味著每個進程都具有它自己的該類待用資料成員的副本。不應共用具有待用資料成員的類。 對於 C++ 類,共用資料區段的初始化要求引起一個特定問題。如果共用資料區段中有類似 CTest Counter(0); 的內容,則當每個進程載入 DLL 時,Counter 對象將在該進程中初始化,從而有可能每次都將對象的資料清零。這與內部資料類型(由連結器在建立 DLL 時初始化)非常不同。 由於存在這些限制,Microsoft 不建議在進程之間共用 C++ 對象。一般情況下,如果希望使用 C++ 在進程之間共用資料,請編寫在內部使用記憶體對應檔來共用資料的類,但不要共用類執行個體本身。在開發這樣的類時,可能需要特別小心,但它使應用程式開發人員能夠完全控制共用資料的副作用。 有關建立命名資料節的更多資訊,請參見位於 http://support.microsoft.com/default.aspx?ln=zh-cn 上的下列知識庫文章: “How to Share Data Between Different Mappings of a DLL”(如何在 DLL 的不同映射之間共用資料)(Q125677)。 “Specifying Shared and Nonshared Data in a DLL”(指定 DLL 中的共用資料和非共用資料)(Q100634)。 “Sharing All Data in a DLL”(共用 DLL 中的所有資料)(Q109619)。 “Memory in Shared Code Sections Is Not Shared Across Terminal Server Sessions”(共用代碼節中的記憶體不在終端伺服器會話間共用)(Q251045)