1. 程式人生 > >__declspec(allocate("segname"))和__declspec( selectany )(AC1)

__declspec(allocate("segname"))和__declspec( selectany )(AC1)

  AC1,由VS2005的ATL嚮導生成的預設COM物件程式碼分析ATL如何實現COM,第一部分。

  為了多多研習ATL想到生成的程式碼,visio、rose、word、excel加上我的筆本全上陣,終於把各個模板類混了個瞭解、跟巨集混了個臉熟。當我藉助偵錯程式想把一個classfactory和com物件的由來看個明白的時候,我發現疑惑很多。不過好在簡單看出了點門道,但要說清楚,非三言兩語可以完成,只好寫個系列以AC1、AC2、ACn等標識。

  __declspec(allocate("segname")) 告訴編譯器分配一個名字為segname的段,譬如:

	__declspec(allocate("LIUAN"))	int	myValue	= 100;

  告訴編譯器,分配一個叫LIUAN的段,把我們的變數myValue存放在那裡,另一種說法是向符號表裡新增myValue符號,使用了這個手段的專案在編譯出來的map檔案裡,可以明顯的發現類似這樣

Start         Length     Name                   Class

0006:00000000 00000104H LIUAN                   DATA

的東西,實際地址可能有差別,但是名字不會變。我們要求編譯器加入新的符號,它做到了。

  在實際使用時,還需要#pragma section事先告訴編譯器,我們要使用的段名,完整的示例是這樣的:

#pragma section("LIUAN", read)

__declspec(allocate("LIUAN"))	int	myValue	= 100;



int _tmain(int argc, _TCHAR* argv[])

{

	printf("%d/n",myValue);

	return 0;

}
Start         Length     Name                   Class

0005:000002fc 00000545H .idata$6                DATA

0006:00000000 00000104H LIUAN                   DATA  //this line

0007:00000000 00000169H .rsrc$01                DATA

  __declspec(selectany)告訴編譯器我要使用pick-any COMDAT,說白了就是跟編譯器說我要在標頭檔案裡初始化東西。在標頭檔案裡初始化整形資料可以藉助enum來模擬實現,但是初始化其他資料就比較難了,selectany給我們提供了一個方式。

//someheader.h

#pragma section("LIUAN", read)



extern "C"	__declspec(allocate("LIUAN"))	__declspec(selectany)	int	myValue	= 100;

__pragma(comment(linker, "/include:_myValue"))

  對於ATL生成的預設com物件,我們開啟map檔案發現有:

0003:0000a344 00000104H  LIUAN                   DATA

  對於ATL生成的預設com物件,我們開啟map檔案發現有

0003:0000a344 00000104H ATL __a                 DATA   0003:0000a448 00000104H ATL __m                 DATA   0003:0000a54c 00000104H ATL __z                 DATA

 是的,這三個變數就是使用了這種手段寫進去的。