一 問題概述
同一個(gè)庫(kù)能不能被多個(gè)進(jìn)程多次加載盛嘿? 答案是it depends.讓我們看看幾種被多次加載的情況。
example 1:
//libtest.a
static char *a[10];
int a_set(int index, char value) {
}
int a_unset(int index) {
}
顯然如果libA(static link)-->libtest libB(static link)-->libtest,對(duì)于程序test依賴于libA和libB,那么libtest.a會(huì)被重復(fù)加載兩次嗡官。在某種情況下撬即,調(diào)用的是libA加載的a_set,而a_unset調(diào)用的是libB的挽拂,那么會(huì)造成結(jié)果不一致或者其他類問題卫旱。因此像libtest.a這種程序不能被同一個(gè)進(jìn)程重復(fù)加載人灼。
如果像下面這種函數(shù)的話
libtest_1.a
void a_set(char *array, int idex, char value) {
array[idex] = value;
}
void a_unset(char *array, int dex) {
array[index] = 0;
}
上面這種函數(shù)及時(shí)被同一個(gè)進(jìn)程多次加載也不會(huì)有問題。
因此一個(gè)so或者a能否被同一個(gè)進(jìn)程多次加載顾翼,這個(gè)視情況而定投放,有的可以有的不可以
二 android下庫(kù)被多次加載問題
從android 8.1 treble開啟之后,谷歌自行對(duì)這樣的庫(kù)有過一次分類适贸,在/system/lib/vndk-sp下的庫(kù)是可以被重復(fù)加載的灸芳,這些都是經(jīng)過谷歌驗(yàn)證的涝桅。同一進(jìn)程多次加載沒有問題。
像這種基礎(chǔ)庫(kù)烙样,被多次加載一般都有什么問題呢冯遂? 以libc++.so為例,總結(jié)大體如下:
libc++有c++_static和c++_shared兩種庫(kù)
Application.mk
APP_STL := c++_static
# Android.mk
include $(CLEAR_VARS)
LOCAL_MODULE := foo
LOCAL_SRC_FILES := foo.cpp
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := bar
LOCAL_SRC_FILES := bar.cpp
LOCAL_SHARED_LIBRARIES := foo
include $(BUILD_SHARED_LIBRARY)
如果一個(gè)進(jìn)程同時(shí)依賴libbar.so和libfoo.so谒获,那么c++_static.a將被進(jìn)程加載兩次蛤肌。有可能會(huì)遇到如下幾類問題:
1) 如果內(nèi)存是在bar.so分配在foo.so釋放的話,會(huì)造成memleak或者堆crash
2) 如果是bar.so拋出的異常被foo.so撲獲的話究反,造成app crash
3) std::cout緩存問題
現(xiàn)在谷歌在ndk開發(fā)中只能使用libc++.so之前使用的libstdc++.so將不被允許寻定,但是可能有些老的庫(kù)是依賴libstdc++.so的儒洛,那么一個(gè)app是否可以同時(shí)依賴libc++.so和libstdc++.so呢精耐?答案是否定的。原因如下:
像std::string這中函數(shù)在這兩個(gè)庫(kù)中的定義是不一樣的琅锻,如果string操作跨STL操作的話卦停,會(huì)出現(xiàn)問題。這種情況同上面靜態(tài)庫(kù)多次加載情況也一樣恼蓬。
三 總結(jié)
因此對(duì)于一個(gè)庫(kù)被重復(fù)加載的情況下惊完,這個(gè)看情況而定,如果不是使用同一個(gè)STL標(biāo)準(zhǔn)的話处硬,需要先統(tǒng)一標(biāo)準(zhǔn)c++后再進(jìn)行編譯小槐。