用vs編譯動態庫需要注意的問題,全域性變數初始化

2021-07-10 13:30:35 字數 1602 閱讀 5579

用vs編譯動態庫如果配置錯誤會導致全域性變數不能初始化。

例子:

string a="hello";

char b="hello";

int main(int arg,char* argv)

編譯成exe後,你可能會認為都是輸出「hello」,但實際結果不盡如此。這取決於你的工程設定。

如果工程屬性裡,鏈結器,入口函式設定為main,那麼結果只有b被列印了,a為空:即:string a=char* b=hello;

這是為什麼呢?

window和wince的動態庫存在乙個入口函式,是_dllmaincrtstartup,這裡面會呼叫_crt_init,這裡面會初始化執行時庫的全域性變數和靜態全域性變數。

其實這一點對於exe應用也是一樣的,但邏輯不同,exe的入口預設是maincrtstartup,裡面同樣會初始化全域性變數和靜態非全域性變數。

也就是說如果你設定了入口函式,系統不會呼叫_crt_init 來執行呼叫建構函式,但是char* 是c語言

下面是msdn的解釋:

c/c++ 執行時庫**執行 dll 啟動序列,從而不必像 windows 3.x 中那樣必須鏈結到單獨的模組。c/c++ 執行時庫**中包含的是名為_dllmaincrtstartup的 dll 入口點函式。_dllmaincrtstartup函式執行若干操作,其中包括呼叫_crt_init,此操作初始化 c/c++ 執行時庫並在靜態非區域性變數上呼叫 c++ 建構函式。如果沒有此函式,執行時庫將保持未初始化狀態。_crt_init既可以用於靜態鏈結的 crt,也可以從使用者 dll 鏈結到 crt dll msvcrt.dll。

雖然可以使用 /entry: 鏈結器選項指定其他入口點函式,但不建議這樣做,因為新的入口點函式將不得不重複_dllmaincrtstartup執行的所有操作。用 visual c++ 生成 dll 時,系統自動鏈結_dllmaincrtstartup,您無需使用 /entry: 鏈結器選項指定入口點函式。

除了初始化 c 執行時庫外,_dllmaincrtstartup還呼叫名為dllmain的函式。根據生成的 dll 型別的不同,visual c++ 為您提供dllmain並使它被鏈結,以便_dllmaincrtstartup始終有東西可以呼叫。這樣,如果不需要初始化 dll,則在生成 dll 時沒有什麼特別的事情要做。如果需要初始化 dll,新增**的位置取決於編寫的 dll 型別。有關更多資訊,請參見初始化 dll。

c/c++ 執行時庫**在靜態非區域性變數上呼叫建構函式和析構函式。例如,在以下 dll 源**中,equus 和 sugar 是 chorse 類的兩個靜態非本地物件,它們都是在 horses.h 中定義的。由於這些物件是在所有函式的外部定義的,源**中沒有任何函式包含對chorse 的建構函式或對析構函式的呼叫。因此,必須由執行時**執行對這些建構函式和析構函式的呼叫。應用程式的執行時庫**也執行此函式。

用UML建模需要注意的問題

用 uml建模時,對軟體開發過程是有要求的,必須是用例驅動,以架構為中心,迭代和遞增的開發,如果軟體開發組織的軟體開發過程不能滿足這三點要求,那麼 uml的使用效果就會大打折扣,下面詳細論述 一 用例驅動 用例驅動意味著為系統定義的用例是整個開發過程的基礎。用例在多個核心工作流程中都發揮了作用。1 ...

用UML建模需要注意的問題

用uml建模時,對軟體開發過程是有要求的,必須是用例驅動,以架構為中心,迭代和遞增的開發,如果軟體開發組織的軟體開發過程不能滿足這三點要求,那麼uml的使用效果就會大打折扣,下面詳細論述 一 用例驅動 用例驅動意味著為系統定義的用例是整個開發過程的基礎。用例在多個核心工作流程中都發揮了作用。1 用例...

需要注意的問題

決策樹id3和c4.5的差別?各自優點?boost演算法 cart 回歸樹用平方誤差最小化準則,分類樹用基尼指數最小化準則 gbdt與隨機森林演算法的原理以及區別。優化演算法中常遇到的kkt條件?作用是?最近鄰演算法knn 分類與回歸 l1和l2函式?l1和l2正則項的比較,如何解決 l1 求導困難...