[問題] static lib 實作 singleton 觀念

作者: dreamboat66 (小嫩)   2019-03-25 23:24:25
最近遇到一個問題 無法理解行為為什麼會是這樣.
我在某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 只會選擇走一
個實作"
這件事很難碰到嗎?
謝謝
作者: steve1012 (steve)   2019-03-25 23:46:00
這樣不是違反odr?
作者: christianSK (AG)   2019-03-26 10:13:00
E.exe 是怎麼call libA.so libB.so去拿instance的?猜測只link到了libA.so/libB.so其中一個.
作者: dreamboat66 (小嫩)   2019-03-26 11:49:00
liba and b.so都各自開一個不同名字的function 裡面都是return GetInst(); E.exe去 呼叫這兩個不同名函數 但得到同一個物件
作者: Lipraxde (Lipraxde)   2019-03-26 14:06:00
他們不是叫同一個 GetInst 嗎
作者: sarafciel (Cattuz)   2019-03-26 14:25:00
好奇問一下 為什麼寫了Singleton卻還要弄兩份XD
作者: dreamboat66 (小嫩)   2019-03-26 14:29:00
希望是同一份 ,但想想覺得可能會兩份,測試起來 竟然真的是一份 ,無法理解為什麼,想知道中間的差異難道載入exe的時候也會扯到odr?
作者: ketrobo (貓蘿蔔)   2019-03-26 15:27:00
target_link_libraries(E PRIVATE A B S S2) 這裡?
作者: dreamboat66 (小嫩)   2019-03-26 16:49:00
@ketrobo: 這部分 實驗 加跟沒加 有沒有差別,結論是沒差都一樣行為,但我忘記貼在這邊之前刪除,謝謝
作者: Lipraxde (Lipraxde)   2019-03-26 17:55:00
libA.so 和 libB.so 有各自的 GetInst,但是 dynamic linker 只會連結到A或B裡面的其中一個。(應該是看誰先被載入)把 -Wl,-Bsymbolic 加到 CXXFLAGS 裡,應該就會拿到不同個 instance 了
作者: dreamboat66 (小嫩)   2019-03-26 18:46:00
意思是 lib ab 各自有同名symbol, 但照順序載入 發現撞名 所以就只載入最一開始的那份,所以libb.so 呼叫到的getinst是a.so的那份?
作者: yilanP (Train Station)   2019-03-26 20:39:00
我有寫過一個class,也是需要兩份,裡面各自需要不同的static member,我是用template處理的,給你參考
作者: Lipraxde (Lipraxde)   2019-03-26 21:01:00
作者: firose (guest也是也是也是也是也)   2019-03-27 08:01:00
這個應該叫 global symbol interpose
作者: cole945 (躂躂..)   2019-03-27 11:23:00
補充一下#1RViGNxg我有回,基本上是依SysV ABI的規則解簡單想成, -la -lb, 在.a和.so的結果會大同小異loader用DT_NEED的順序解,多層依BFD找. DT_NEED的順序是linktime決定, 所以 A B 就決定是找 A 的版本. 大致這樣

Links booklink

Contact Us: admin [ a t ] ucptt.com