亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費(fèi)注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 4932 | 回復(fù): 9
打印 上一主題 下一主題

[C++] C++ Static Lib 鏈接問題 [復(fù)制鏈接]

論壇徽章:
1
雙子座
日期:2014-08-29 17:15:03
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2010-07-22 10:45 |只看該作者 |倒序瀏覽
Static Lib 里面的代碼:

MsgDefs.h:
  1. #pragma once

  2. #include <map>
  3. #include <string>

  4. typedef std::pair<std::string, int> MsgDefKey;
  5. typedef std::map<MsgDefKey, std::string> MsgDefs;
  6. extern MsgDefs gHSVFMsgDefs;
  7. extern int fake_link_var;
  8. int fake_link_func();

  9. #define MSG_DEF(version, msg_id, msg) \
  10.         namespace version##_##msg_id##_def \
  11.         { \
  12.                 MsgDefs::key_type key(#version, msg_id); \
  13.                 struct DefsAppender \
  14.                 { \
  15.                         DefsAppender() \
  16.                         { \
  17.                         gHSVFMsgDefs.insert(MsgDefs::value_type(key, msg)); \
  18.                         } \
  19.                 } defs_appender; \
  20.         }
復(fù)制代碼
Version1.cpp:
  1. #include "stdafx.h"
  2. #include "MsgDefs.h"
  3. #include <string>

  4. using namespace std;

  5. MsgDefs gHSVFMsgDefs;
  6. const std::string V1_1 = "A1";
  7. MSG_DEF(V1, 1, V1_1)
復(fù)制代碼
Version2.cpp:
  1. #include "stdafx.h"
  2. #include "MsgDefs.h"
  3. #include <string>

  4. using namespace std;
  5. int fake_link_var = 0;
  6. int fake_link_func()
  7. {
  8.         return 0;
  9. }

  10. const std::string V2_1 = "B1";
  11. MSG_DEF(V2, 1, V2_1)
復(fù)制代碼
主程序代碼:
  1. // LinkTest.cpp : Defines the entry point for the console application.
  2. //

  3. #include "stdafx.h"
  4. #include "MsgDefs.h"
  5. #include <iostream>

  6. int _tmain(int argc, _TCHAR* argv[])
  7. {
  8.         //fake_link_var();
  9.         //fake_link_var++;
  10.         std::cout << gHSVFMsgDefs.size() << std::endl;
  11.         return 0;
  12. }

復(fù)制代碼
問題: 注釋掉fake_link_var那兩行,輸出結(jié)果為1.  啟用任意一行代碼后,結(jié)果為2.  求達(dá)人賜教更好的解決方案.

論壇徽章:
1
雙子座
日期:2014-08-29 17:15:03
2 [報告]
發(fā)表于 2010-07-22 10:46 |只看該作者
如果代碼都是放在主程序中的話就沒有任何問題(輸出結(jié)果為2)

論壇徽章:
1
雙子座
日期:2014-08-29 17:15:03
3 [報告]
發(fā)表于 2010-07-22 11:31 |只看該作者
Up期待滑鐵盧進(jìn)來看看

論壇徽章:
2
青銅圣斗士
日期:2015-11-26 06:15:59數(shù)據(jù)庫技術(shù)版塊每日發(fā)帖之星
日期:2016-07-24 06:20:00
4 [報告]
發(fā)表于 2010-07-22 15:14 |只看該作者
翻譯單元version1:

  1. MsgDefs gHSVFMsgDefs;
  2. const std::string V1_1 = "A1";
  3. MSG_DEF(V1, 1, V1_1); // 這里沒問題
復(fù)制代碼
version2:

  1. const std::string V2_1 = "B1";
  2. MSG_DEF(V2, 1, V2_1); // 這里需要gHSVFMsgDefs已經(jīng)初始化
復(fù)制代碼
但多個翻譯單元間的全局變量初始化順序是沒有保證的。



如果MSG_DEF(V2, 1, V2_1)展開定義的那個全局變量先于gHSVFMsgDefs初始化,
那就是向一個未初始化的map插入數(shù)據(jù) —— 很危險。
然后gHSVFMsgDefs初始化, 然后MSG_DEF(V1, 1, V1_1)插入一項。
最終就只有1項。

論壇徽章:
1
雙子座
日期:2014-08-29 17:15:03
5 [報告]
發(fā)表于 2010-07-22 17:02 |只看該作者
回復(fù) 4# OwnWaterloo


    首先可以肯定的是代碼確實很有問題,如果初始化順序出錯的話。 可能改成Singleton會安全些。  但是改成單件后,卻發(fā)現(xiàn)結(jié)果為0.  調(diào)試出來的結(jié)果是所有靜態(tài)對象都沒有初始化。
  1. #pragma once

  2. #include <map>
  3. #include <string>

  4. typedef std::pair<std::string, int> MsgDefKey;
  5. typedef std::map<MsgDefKey, std::string> MsgDefs;
  6. //extern MsgDefs gHSVFMsgDefs;

  7. MsgDefs& getInstance()
  8. {
  9.         static MsgDefs obj;
  10.         return obj;
  11. }

  12. extern int fake_link_var;
  13. int fake_link_func();

  14. #define MSG_DEF(version, msg_id, msg) \
  15.         namespace version##_##msg_id##_def \
  16.         { \
  17.                 MsgDefs::key_type key(#version, msg_id); \
  18.                 struct DefsAppender \
  19.                 { \
  20.                         DefsAppender() \
  21.                         { \
  22.                         getInstance().insert(MsgDefs::value_type(key, msg)); \
  23.                         } \
  24.                 } defs_appender; \
  25.         }
復(fù)制代碼
  1. // LinkTest.cpp : Defines the entry point for the console application.
  2. //

  3. #include "stdafx.h"
  4. #include "MsgDefs.h"
  5. #include <iostream>

  6. int _tmain(int argc, _TCHAR* argv[])
  7. {
  8.         //fake_link_var();
  9.         //fake_link_var++;
  10.         //std::cout << gHSVFMsgDefs.size() << std::endl;
  11.         std::cout << getInstance().size() << std::endl;
  12.         return 0;
  13. }


復(fù)制代碼

論壇徽章:
0
6 [報告]
發(fā)表于 2010-07-22 18:36 |只看該作者
有時看到c++代碼會覺得很難看!

論壇徽章:
2
青銅圣斗士
日期:2015-11-26 06:15:59數(shù)據(jù)庫技術(shù)版塊每日發(fā)帖之星
日期:2016-07-24 06:20:00
7 [報告]
發(fā)表于 2010-07-22 21:44 |只看該作者
回復(fù) 5# srdgame

你先這樣試試:

1. 初始化

map的初始化和4樓一樣。

作為一個函數(shù)中的static 對象, 初始化時機(jī)是控制線第1次到達(dá)定義處。
同時不要在main之前多線程訪問這個函數(shù)。

這樣就保證初始化順序是沒問題的。

2. 優(yōu)化

你用的應(yīng)該是msvc吧?
試試取消優(yōu)化后會不會得到正確結(jié)果?
再試試訪問一次那個用于插入項的全局對象。

有可能是因為插入項的全局對象沒有被使用, 而被鏈接器優(yōu)化了。

  1. ------ def.h ------
  2. #include <map>

  3. extern
  4. std::map
  5. <std::pair<std::string,int>
  6. ,std::string
  7. > msg;

  8. msg& instance() { static msg m; return m; }

  9. struct msg_init
  10. {
  11.   msg_init(char const* v, int id, char const* m)
  12.   {
  13.     instance().insert
  14.     (std::make_pair(std::make_pair(v,id), m);
  15.   }
  16. };


  17. ------ version1.cpp ------
  18. #include "def.h"
  19. msg_init v1("V1", 1, "A1");


  20. ------ version2.cpp
  21. #include "def.h"
  22. msg_init v2("V2", 2, "B1");

  23. ------ linktest.cpp ------
  24. #include <iostream>
  25. #include "def.h"

  26. extern msg_init v1, v2;

  27. int main()
  28. {
  29.       using namespace std;
  30.       // 這里, 試試取消/添加下面2行
  31.       // 會不會產(chǎn)生不同的輸出
  32.       cout<<&v1<<endl;
  33.       cout<<&v2<<endl;
  34.       cout<<instance().size()<<endl;
  35.       return 0;
  36. }

復(fù)制代碼
如果會輸出不同結(jié)果, 那就肯定不是因為初始化順序, 而是v1, v2被鏈接器排除了。
以前在cppblog看到過這樣的情況: http://www.cppblog.com/kevinlynx/archive/2010/02/10/105885.html

那個文章里使用的是一個const, 默認(rèn)是static鏈接, 所以我認(rèn)為可能會被優(yōu)化。
而外部鏈接, 應(yīng)該不會被優(yōu)化才對, 否則造成程序結(jié)果有可見差異。
后來也沒去驗證。

從你的情況來看, 可能真的會被優(yōu)化。

論壇徽章:
1
雙子座
日期:2014-08-29 17:15:03
8 [報告]
發(fā)表于 2010-07-23 11:29 |只看該作者
是的,被優(yōu)化(或者干脆說這就是鏈接器的工作原則)了。   跟cppblog上描述的問題應(yīng)該是一樣的。

論壇徽章:
2
青銅圣斗士
日期:2015-11-26 06:15:59數(shù)據(jù)庫技術(shù)版塊每日發(fā)帖之星
日期:2016-07-24 06:20:00
9 [報告]
發(fā)表于 2010-07-23 16:39 |只看該作者
回復(fù) 8# srdgame

然后?  如何解決?
真的寫個函數(shù)去引用一下?  太缺乏美感了……

如果不是做成靜態(tài)庫, 會有這個問題么?

論壇徽章:
1
雙子座
日期:2014-08-29 17:15:03
10 [報告]
發(fā)表于 2010-07-26 14:45 |只看該作者
回復(fù)  srdgame

然后?  如何解決?
真的寫個函數(shù)去引用一下?  太缺乏美感了……

如果不是做成靜態(tài) ...
OwnWaterloo 發(fā)表于 2010-07-23 16:39



暫時沒有思路,目前只能通過寫個函數(shù)/變量去引用一下。  沒去試動態(tài)鏈接。 在可執(zhí)行程序工程里面是沒有問題的(有問題的話CPPUnit早死了)。
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP