青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

loop_in_codes

低調做技術__歡迎移步我的獨立博客 codemaro.com 微博 kevinlynx

靜態庫中全局變量的初始化問題

 

在我自己寫的一個工廠類實現中,每個產品會注冊創建接口到這個工廠類。工廠類使用這些
注冊進來的創建接口來完成產品的創建。其結構大致如下:

product *factory::create( long product_type )
{
    creator c = m_creators[product_type];
    return c();
}

factory::instance().register( PRODUCT_A_TYPE, productA::create );
...
factory::instance().create( PRODUCT_A_TYPE );

這個很普通的工廠實現中,需要寫上很多注冊代碼。每次添加新的產品種類時,也需要修改
這些的注冊代碼。而恰好,這些注冊代碼可能會被放在一個統一的地方。為了消除這個地方
,我使用了偶然間看到的<Modern C++ design>里的做法:

const bool _local = factory::instance().register( PRODUCT_A_TYPE,...

也就是說,通過對全局常量_local的自動初始化,來自動完成對該產品的注冊。

結果,因為這些代碼全部被放置于一個靜態庫。最終的代碼文件結構大致為:

lib
    - product_a.cpp : 定義了全局常量_local
    - product_a.h
    - factory.cpp
    - factory.h
exe
    - main.cpp

現在看起來世界很美,因為factory甚至不知道世界上還有個跟上層邏輯相關的product_a。
這種模塊耦合幾乎為0的結構讓我竊喜。

悲劇的事情首先發生于,開VC調試器,發現打在product_a.cpp里的斷點失效。就是那個總
是提示說沒有為該文件加載調試符號。開始還不在意,以為又是代碼和調試符號文件不匹配
的原因,折騰了好久,不得其果。

后來分析了下,發現這個調試提示,就像我開著調試器打開了一個非本工程的代碼文件,而
斷點就打在這個文件里一樣。也就是說,VC把我product_a.cpp當成不是這個工程里的代碼
文件。

按照這個思路寫些實驗代碼,最終發現問題所在:VC鏈接器根本沒鏈接進product_a.cpp里
的代碼。表現出來的情況就是,該編譯單元里的全局常量(全局變量一樣)根本沒有得到初
始化,因為我跟到factory::register并沒有被調用到。為什么VC不鏈接這個編譯單元對應
的目標文件?或者說,為什么VC不初始化這個全局常量?

原因就在于,product_a.cpp太獨立了。一個在整個編譯鏈接階段都無法確定該文件是否被
使用的文件,VC就直接不鏈接了。相反,當在factory.cpp里寫下類似代碼:

void test()
{
    product_a obj;
}

雖然說test函數不會被調用,一切情況也變得正常了。好了,不扯了,給最后我的結論:

1、如果靜態庫中某個編譯單元在編譯階段被確認為它并沒有被外部使用,那么當這個靜態
庫被鏈接進可執行文件時,鏈接器忽略掉該編譯單元里的代碼,那么,鏈接器自然也不會為
該編譯單元里出現的全局變量常量生成初始化代碼(關于這部分初始化代碼可以閱讀
<linker and loader>一書);
2、上面那條結論存在一種傳染性,意思是,當可執行文件里的代碼使用到靜態庫中文件A里
的代碼,A里又有地方使用到B里的代碼,那么B依然會被鏈接。這種依賴性,應該可以讓編
譯器在編譯階段就發現(顯然,上面我舉的例子里,factory只有在運行期間才會依賴到
product_a.cpp里的代碼)

posted on 2010-01-17 19:34 Kevin Lynx 閱讀(15785) 評論(19)  編輯 收藏 引用 所屬分類: c/c++通用編程

評論

# re: 靜態庫中全局變量的初始化問題 2010-01-17 20:08 OwnWaterloo

試試在product_a.cpp中, 將:
const bool _local = factory::instance().register( PRODUCT_A_TYPE,...
改為:
extern const bool local_ = factory::instance()...
或者:
namespace {
extern const bool local = ...
}

可能有效,可能無效。


即使有效,依然不能保證local的初始化順序。main之后執行的代碼,可以保證所有產品已經被注冊,main之前沒有保證。
  回復  更多評論   

# re: 靜態庫中全局變量的初始化問題 2010-01-17 22:41 LOGOS

const bool _local = factory::instance().register( PRODUCT_A_TYPE,...
wow, are u crazy?  回復  更多評論   

# re: 靜態庫中全局變量的初始化問題 2010-01-17 23:00 Kevin Lynx


@OwnWaterloo
@LOGOS
加extern是什么意思?文章中的例子,只是因為鏈接器沒有為靜態庫中的全局對象生成初始化代碼。我也并不關心每一個local的初始化順序,因為他們是全局的,所以他們肯定會先于main被初始化。整個文章的意思,其實是說,鏈接器并沒有生成這個自動初始化的代碼,因為鏈接器覺得這幾個“沒有”被使用的全局對象不需要,所以就沒生成。

  回復  更多評論   

# re: 靜態庫中全局變量的初始化問題 2010-01-17 23:04 OwnWaterloo

@Kevin Lynx
在C++中, 非local的const對象, 默認是staic鏈接……

a.cpp
int g_i;

雖然g_i也不一定能被添加到最終代碼中, 但機會應該比:

a.cpp
static int g_i; 要大。
  回復  更多評論   

# re: 靜態庫中全局變量的初始化問題 2010-01-18 04:19 藥品中國網

很好 學習了。  回復  更多評論   

# re: 靜態庫中全局變量的初始化問題 2010-01-18 08:52 Kevin Lynx

@OwnWaterloo
這個機會是什么意思?  回復  更多評論   

# re: 靜態庫中全局變量的初始化問題 2010-01-19 12:06 OwnWaterloo

@Kevin Lynx
編譯器根據什么規則來判斷某個沒有被使用的符號可以不必鏈接到binary中?
這個規則我不了解, 可能C++標準有描述, 也可能沒有。

我只是猜想 :
1. 如果某個extern符號沒有被鏈接到binary中, 那將其改為static, 應該也不會被鏈接到binary中。
2. 如果某個static符號沒有被鏈接到binary中, 那將其改為extern, 也許就會被鏈接到binary中。

這就是機會的意思。

btw, 改為extern const 有效么?
  回復  更多評論   

# re: 靜態庫中全局變量的初始化問題 2010-01-20 09:14 Kevin Lynx

@OwnWaterloo
一樣的。  回復  更多評論   

# re: 靜態庫中全局變量的初始化問題 2010-01-20 19:44 李現民

我以前也試過這樣的方法, 項目用的是vc6,只debug版本下對象是可以生生的,release版本中就被人優化掉了,沒有找到保持這種級別低耦合度的替代方案。
到現在為止, 我寫的那個factory類再也沒有用過,因為看不到優勢在哪里, 還不如現寫一個工廠來得清晰  回復  更多評論   

# re: 靜態庫中全局變量的初始化問題 2010-02-09 19:44 金慶

Issues with static variables in static libraries
( http://social.msdn.microsoft.com/Forums/en/vclanguage/thread/5c5ee89d-2a38-483d-8550-484550901170 )

You can use the /INCLUDE linker option:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore/html/_core_.2f.INCLUDE.asp

Or you place a #pragma in your code like this:
#pragma comment(linker, "/include:SymbolToUse")
  回復  更多評論   

# re: 靜態庫中全局變量的初始化問題 2010-02-10 12:14 李現民

@金慶
不好使
我想應該是這個問題:
Only problem is that the symbol is not very...simple. I have a class called fxAttributeEditor, but you can't just do /include:fxAttributeEditor. The symbol is actually:

??_C@_0BC@OFGGEBAJ@fxAttributeEditor?$AA@

And that does work, but having to add that seems like a terrible coding decision. It seems like going the dynamic library route would be far better. I've had a variety of really good reasons for not wanting to do that. I'm not against DLLs, but in some cases (like mine) I don't believe it's the best choice. Is there not any better way to go about this?

Thanks,

這是引用原文, 大概意思是“不能夠在#pragma comment(linker, /include:)中直接使用你定義的那個變量名”,因為c++編譯時會將其改為??_C@_0BC@OFGGEBAJ@fxAttributeEditor?$AA@這樣的的形式。

我不知道是不是真的這樣, 但我的實驗結果是找不到我自己定義的變量名  回復  更多評論   

# re: 靜態庫中全局變量的初始化問題 2010-02-10 15:52 金慶

@李現民
試了一下,確實如此。我打開lib文件查到了加了前后綴的變量名,然后在主調程序中添加/include指令,這樣才有效。我原來以為只需加在靜態庫中呢。實際上,靜態庫中加不加/include指令,都會輸出符號。但是static變量是無論如何都不會輸出符號的。/include指令與引用該符號的作用一樣。所以我的結論是應該輸出一個init()函數來初始化靜態庫。  回復  更多評論   

# re: 靜態庫中全局變量的初始化問題 2010-02-10 16:43 Kevin Lynx

@金慶
@李現民
3q for your comments.
今天隨便看了個文檔http://linux.chinaunix.net/bbs/thread-910296-1-1.html,<Linker Algorithm.pdf>恰好在里面看到和我這里提到的相同的2點結論  回復  更多評論   

# re: 靜態庫中全局變量的初始化問題 2011-11-07 01:15 溪流

這個問題最終解決了嗎?  回復  更多評論   

# re: 靜態庫中全局變量的初始化問題 2011-11-07 09:46 Kevin Lynx

@溪流
解決辦法就是換成常規方法:顯示初始化。  回復  更多評論   

# re: 靜態庫中全局變量的初始化問題 2011-11-07 10:35 李現民

@Kevin Lynx
這個問題后來我試過,在我的項目里( 前面提到的,使用了VC6),問題出在使用singleton生成單個factory對象的地方。如果將factory的構造函數設計為private,同時提供一個類get_instance()的public static方法,會產生多個factory實例。具體表現就是,register()函數的確執行了, 但是所有的注冊內容都注冊到了第一個factory對象身上,等到運行期使用create方法的時候,使用的卻是后面新生成的factory對象,因此會發生沒有注冊過的假象。

解決方法為:將factory()構造函數聲明為public,在factory類外面定義一個singleton函數,并一直使用這個函數進行注冊與創建。但這種方法的缺點是你無法從語法上確保所有用戶使用的都是這個singleton對象。

懷疑為VC6的bug,不過由于已經基本滿足了需要,未繼續深究。  回復  更多評論   

# re: 靜態庫中全局變量的初始化問題 2013-06-16 11:14 戴進

在頭文件中

#ifndef _DEF_AUTO_FACTORY
#define _DEF_AUTO_FACTORY
static CFactory __AutoFactory;
#endif

這樣能解決問題,但是間接的也導致了你的這個類被公開了。  回復  更多評論   

# re: 靜態庫中全局變量的初始化問題 2013-06-16 13:36 戴進

我暫時性是這么解決自動初始化靜態庫的。


a.cpp中,有一個類

class a
{
public:
a()
{
...這里初始化
}

~a()
{
...這里做釋放
}

bool _LinkProc(){return true;}
//這個函數,也就是為了鏈接用的。
};

a m_a;//全局變量

bool b = m_a._LinkProc();
//實際上光是這樣,也還是不會鏈接,那怎么辦呢,問了下度娘,她說,要訪問到的全局變量,才會鏈接,那么最后我們到頭文件中。

h文件中
extern bool b;//注意extern只是引用,不等同于訪問。
static bool c = b;//這里對b的訪問,就自動鏈接到



  回復  更多評論   

# re: 靜態庫中全局變量的初始化問題 2014-05-15 19:35 HK

兄弟,這個問題我也遇到了,我采用的方法是新建一個新的.cpp文件(for_register.cpp)
然后“const bool _local = factory::instance().register( PRODUCT_A_TYPE,... ”這個定義在 for_register.cpp這個文件里
最后在一定能被鏈接進去的一個.cpp里 include " for_register.cpp"
這樣基本上就解決了。
你每新增一個產品就要到 for_register.cpp里面去注冊一下。  回復  更多評論   

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲乱码国产乱码精品精天堂| 欧美精品v国产精品v日韩精品| 久久综合伊人| 欧美在线播放一区| 久久久久久久尹人综合网亚洲 | 9国产精品视频| 夜夜爽www精品| 亚洲综合色噜噜狠狠| 欧美在线二区| 欧美黄色网络| 国产免费成人av| 亚洲第一主播视频| 日韩午夜精品视频| 亚洲一区国产精品| 亚洲天堂偷拍| 欧美一级片在线播放| 久久久久国产精品www| 欧美成年人视频| 99国产精品视频免费观看一公开 | 欧美一区激情| 欧美激情精品久久久久| 国产精品一区视频| 亚洲国产一二三| 亚洲欧美日韩一区二区在线 | 久久精品视频在线| 91久久精品国产91久久性色| 亚洲欧洲免费视频| 欧美中文字幕第一页| 欧美噜噜久久久xxx| 国内久久婷婷综合| 亚洲欧美日韩在线综合| 亚洲大片在线| 久久精品国产视频| 国产精品久久久99| 日韩午夜在线电影| 牛牛影视久久网| 欧美一区不卡| 国产伦精品一区二区三区视频孕妇 | 亚洲一区二区在线播放| 女女同性精品视频| 黑人极品videos精品欧美裸| 亚洲一区二区三区四区视频| 亚洲国产一二三| 久久综合伊人77777蜜臀| 国产欧美日韩激情| 亚洲尤物视频在线| 99re成人精品视频| 欧美国产日本韩| 亚洲国产精品第一区二区三区| 欧美一区二区在线观看| 亚洲天堂免费观看| 欧美日韩综合视频| 一区二区三欧美| 亚洲黄页一区| 欧美日韩国产123区| 亚洲精品日韩在线| 亚洲国产cao| 欧美激情国产日韩精品一区18| 亚洲高清久久网| 免费久久精品视频| 国产精品久久久久久一区二区三区| 国产精品美女一区二区在线观看| 亚洲日本成人网| 亚洲国产中文字幕在线观看| 久久久久综合网| 亚洲国产天堂网精品网站| 久久黄色网页| 欧美一区二区视频网站| 好吊色欧美一区二区三区四区| 久久精品91久久香蕉加勒比| 亚洲欧美中文日韩在线| 国产精品亚洲综合| 久久免费国产精品1| 欧美制服丝袜| 在线观看视频亚洲| 欧美高清你懂得| 欧美精品一区二区三区很污很色的 | 亚洲人成免费| 欧美日韩性生活视频| 亚洲欧美日韩人成在线播放| 亚洲视频碰碰| 国产日韩欧美在线播放不卡| 欧美在线国产| 美女久久一区| 亚洲午夜在线视频| 久久成人这里只有精品| 99国产精品久久久久久久| 一区二区日韩精品| 国产一区二区三区在线观看免费视频 | 亚洲一区二区视频在线| 一区二区日韩伦理片| 国产欧美日韩专区发布| 久久一区二区精品| 欧美二区在线| 性色av一区二区三区| 久久精品在线观看| 99re66热这里只有精品3直播| 亚洲永久视频| 亚洲片国产一区一级在线观看| 亚洲人成在线播放| 国产精品久久久久毛片软件 | 国产一二三精品| 亚洲国产精品成人一区二区 | 欧美华人在线视频| 亚洲免费伊人电影在线观看av| 欧美影院在线播放| 亚洲欧洲一区二区在线观看| 亚洲欧美精品在线| 亚洲一区二三| 欧美日本亚洲视频| 久久精品国产一区二区电影| 老牛影视一区二区三区| 亚洲欧美视频在线| 免费亚洲电影在线| 久久aⅴ国产欧美74aaa| 欧美日韩高清不卡| 美女国产一区| 国产日韩综合| 99精品国产热久久91蜜凸| 一区在线观看视频| 亚洲欧美日韩另类精品一区二区三区| 亚洲另类自拍| 久久在线免费视频| 久久综合九色综合久99| 国产精品一卡| aa日韩免费精品视频一| 亚洲精品综合精品自拍| 久久亚洲捆绑美女| 久久精品国产精品| 国产精品网站一区| 日韩亚洲欧美精品| 一本色道久久综合亚洲二区三区| 乱码第一页成人| 美女网站久久| 亚洲国产日韩在线一区模特| 久久免费国产精品| 欧美a一区二区| 亚洲高清不卡一区| 欧美成人首页| 91久久久久| 亚洲免费久久| 欧美日韩网站| 亚洲欧美www| 久久精品视频va| 狠狠色伊人亚洲综合网站色| 久久久xxx| 欧美成人自拍视频| 日韩西西人体444www| 欧美三日本三级少妇三99| 亚洲一区二区高清| 久久久精品2019中文字幕神马| 国精产品99永久一区一区| 亚洲欧美日韩国产一区| 午夜免费在线观看精品视频| 国产精品视频一区二区三区 | 久久综合成人精品亚洲另类欧美| 国产综合久久久久久鬼色| 久久综合久久久久88| 亚洲欧洲精品一区二区三区波多野1战4| 亚洲黄色成人| 欧美日韩在线免费观看| 亚洲免费在线观看| 免费在线视频一区| 一区二区三区日韩精品| 国产精品一区一区三区| 久久久999精品免费| 91久久久在线| 久久精品99无色码中文字幕| 在线精品高清中文字幕| 欧美午夜电影网| 久久久久久久久一区二区| 亚洲激情成人在线| 久久国产欧美| 日韩午夜av电影| 国产一区二区视频在线观看 | 亚洲直播在线一区| 国产午夜亚洲精品理论片色戒| 久久综合综合久久综合| 国产精品99久久久久久久vr| 美女视频黄 久久| 亚洲一区免费网站| 亚洲高清不卡在线观看| 国产精品久久午夜夜伦鲁鲁| 免费观看成人www动漫视频| 亚洲欧美国产精品桃花| 最近中文字幕mv在线一区二区三区四区 | 日韩视频中文字幕| 精品成人a区在线观看| 国产精品v欧美精品v日本精品动漫| 久久精品国产99精品国产亚洲性色| 日韩视频在线观看国产| 欧美r片在线| 久久久久九九九九| 亚洲伊人久久综合| 亚洲精品免费在线播放| 伊人久久大香线蕉综合热线| 国产精品揄拍500视频| 欧美日韩亚洲国产一区| 欧美国产高清| 麻豆国产精品777777在线 |