看板 C_and_CPP 關於我們 聯絡資訊
最近遇到一個問題 無法理解行為為什麼會是這樣. 我在某static lib 稱作libS.a 裡面實作了一個簡單的singleton (介面為GetInst) 我有兩個dynamic lib, (libA.so, libB.so) 都使用這S.a , 而E.exe是link 這兩個.so 而沒有直接使用.a 附上Cmake file 可以比較明確知道關係 set(CMAKE_CXX_VISIBILITY_PRESET hidden) add_library(S STATIC s.cpp) add_library(S2 STATIC s2.cpp) <==這邊故意改成S2 讓他變成兩個.a add_library(A SHARED a.cpp) target_link_libraries(A PRIVATE S) add_library(B SHARED b.cpp) target_link_libraries(B PRIVATE S2) <==故意, 原本寫S也是一樣結果 add_executable(E main.cpp) target_link_libraries(E PRIVATE A B S S2) 我的問題是 因為是.a 我用nm看A.so跟B.so裡面都有 "GetInst"這symbol 我預期他們各自有獨立的singleton, 意思是從GetInst拿到的instance要不一樣 我用E.exe去驗證這件事, 沒想到 拿到的竟然是一樣的instance, 我故意夾個log 並且把s.cpp 複製一份叫做s2.cpp 然後產出libS2.a 如上CMake所述 我能發現的是 E.exe執行的時候 最後呼叫到static library的時候 他只會走其中一個 實作 這邊給我的感覺可能扯到ODR, 但我整件事兜不起來覺得很困惑 如果今天libS.a不是static而是libS.so, 整件事應該相當合理 可是它是static lib 最後卻只有一份 是有什麼設定我沒有做 還是這非常正常....如果是可否給我一些觀念上的補充 因為以我這簡單的lib間的關係 難道"兩個.so 用到不同的.a 而這不同的.a有相同symbol 最後產出的exe 只會選擇走一 個實作" 這件事很難碰到嗎? 謝謝 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 27.247.94.8 ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1553527468.A.0C4.html
steve1012: 這樣不是違反odr? 03/25 23:46
christianSK: E.exe 是怎麼call libA.so libB.so去拿instance的? 03/26 10:13
christianSK: 猜測只link到了libA.so/libB.so其中一個. 03/26 10:14
dreamboat66: liba and b.so都各自開一個不同名字的function 裡面 03/26 11:49
dreamboat66: 都是return GetInst(); E.exe去 呼叫這兩個不同名 03/26 11:49
dreamboat66: 函數 但得到同一個物件 03/26 11:49
Lipraxde: 他們不是叫同一個 GetInst 嗎 03/26 14:06
sarafciel: 好奇問一下 為什麼寫了Singleton卻還要弄兩份XD 03/26 14:25
dreamboat66: 希望是同一份 ,但想想覺得可能會兩份,測試起來 竟 03/26 14:29
dreamboat66: 然真的是一份 ,無法理解為什麼,想知道中間的差異 03/26 14:29
dreamboat66: 難道載入exe的時候也會扯到odr? 03/26 14:29
ketrobo: target_link_libraries(E PRIVATE A B S S2) 這裡? 03/26 15:27
dreamboat66: @ketrobo: 這部分 實驗 加跟沒加 有沒有差別,結論是 03/26 16:49
dreamboat66: 沒差都一樣行為,但我忘記貼在這邊之前刪除,謝謝 03/26 16:49
Lipraxde: libA.so 和 libB.so 有各自的 GetInst,但是 dynamic l 03/26 17:55
Lipraxde: inker 只會連結到A或B裡面的其中一個。(應該是看誰先被 03/26 17:55
Lipraxde: 載入) 03/26 17:55
Lipraxde: 把 -Wl,-Bsymbolic 加到 CXXFLAGS 裡,應該就會拿到不 03/26 17:55
Lipraxde: 同個 instance 了 03/26 17:55
dreamboat66: 意思是 lib ab 各自有同名symbol, 但照順序載入 發現 03/26 18:46
dreamboat66: 撞名 所以就只載入最一開始的那份,所以libb.so 呼叫 03/26 18:46
dreamboat66: 到的getinst是a.so的那份? 03/26 18:46
yilanP: 我有寫過一個class,也是需要兩份,裡面各自需要不同的st 03/26 20:39
yilanP: atic member,我是用template處理的,給你參考 03/26 20:39
Lipraxde: https://goo.gl/1iakKJ 03/26 21:01
firose: 這個應該叫 global symbol interpose 03/27 08:01
cole945: 補充一下#1RViGNxg我有回,基本上是依SysV ABI的規則解 03/27 11:23
cole945: 簡單想成, -la -lb, 在.a和.so的結果會大同小異 03/27 11:23
cole945: loader用DT_NEED的順序解,多層依BFD找. DT_NEED的順序是 03/27 11:24
cole945: linktime決定, 所以 A B 就決定是找 A 的版本. 大致這樣 03/27 11:25