記錄一次采坑--如何處理Linux動(dòng)態(tài)庫同名函數(shù)?-創(chuàng)新互聯(lián)

一、背景介紹

需求描述:業(yè)務(wù)提供一個(gè)鑒權(quán)的靜態(tài)庫,我只需要從url 和 參數(shù)中提取相應(yīng)的參數(shù)傳給業(yè)務(wù)的靜態(tài)庫,將靜態(tài)庫的處理結(jié)果直接返回給業(yè)務(wù)(return < 0, 直接返回403)。

創(chuàng)新互聯(lián)建站專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于成都做網(wǎng)站、成都網(wǎng)站制作、成都外貿(mào)網(wǎng)站建設(shè)、白塔網(wǎng)絡(luò)推廣、微信小程序開發(fā)、白塔網(wǎng)絡(luò)營銷、白塔企業(yè)策劃、白塔品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運(yùn)營等,從售前售中售后,我們都將竭誠為您服務(wù),您的肯定,是我們大的嘉獎(jiǎng);創(chuàng)新互聯(lián)建站為所有大學(xué)生創(chuàng)業(yè)者提供白塔建站搭建服務(wù),24小時(shí)服務(wù)熱線:028-86922220,官方網(wǎng)址:muchs.cn

但是最近業(yè)務(wù)反饋,請(qǐng)求部分url直接返回Error:-1015錯(cuò)誤,不符合預(yù)期。

二、分析過程

業(yè)務(wù)剛開始反饋問題,我的第一反應(yīng):怎么可能是我的問題,我就僅僅寫了一個(gè)so(暫時(shí)命名1.so),直接調(diào)用了你們靜態(tài)庫,這個(gè)-1015不就是你們庫返回的結(jié)果。 有問題也是業(yè)務(wù)提供的庫有問題。 或者就是業(yè)務(wù)配置不正確。
我臨時(shí)解決方案:

  1. 讓業(yè)務(wù)檢查配置 ,是否和校驗(yàn)級(jí)別有關(guān)系?
  2. 雙方md5的靜態(tài)庫,本地調(diào)試結(jié)果是否正確?
  3. 上述方案不行: 采用最挫的方案, 既然靜態(tài)庫吐出來的結(jié)果,瘋狂加printf,我就不信這個(gè)邪了

最后還是走到方案3,業(yè)務(wù)說printf的結(jié)果不符合預(yù)期,經(jīng)業(yè)務(wù)提醒,突然意識(shí)到是不是調(diào)用鏈接到其他庫的xx_func?

因?yàn)轫?xiàng)目比較大, 涉及的庫比較多,我用nm認(rèn)真檢查了編譯時(shí)加載的庫,竟然還真找到一模一樣的接口xx_func

nm   ./lib/liba.a | grep xx_func

記錄一次采坑--如何處理Linux動(dòng)態(tài)庫同名函數(shù)?
編譯代碼的時(shí)候,趕緊去掉了同名函數(shù)庫(因?yàn)樵趍akefile文件編譯的時(shí)候某些公共庫默認(rèn)都會(huì)編譯進(jìn)去)。重新編譯版本。

沒有想到,去掉同名函數(shù)庫,還是存在問題,為什么呢?到底是哪里的問題?

隨手直接 nm *.so | grep xx_func,結(jié)果在另外一個(gè)so(暫時(shí)命名2.so)中,發(fā)現(xiàn)了同名函數(shù)xx_func。 看了一下配置,程序啟動(dòng)的時(shí)候首先加載了2.so動(dòng)態(tài)庫, 1.so是在2.so后面加載的. 因?yàn)閮?yōu)先加載哪個(gè)庫,就使用哪個(gè)庫的同名函數(shù),并不會(huì)覆蓋的情況(自己現(xiàn)網(wǎng)測(cè)試 + 測(cè)試代碼)

到這里問題的原因也算是找到了,下面接著就是如何解決問題?

三、解決方案

1. 最簡單的方案 -- 修改函數(shù)名稱

因?yàn)闃I(yè)務(wù)本身提供的靜態(tài)庫,用nm查看函數(shù)也不多,為了安全起見,修改每個(gè)函數(shù)的名稱(增加一些業(yè)務(wù)私有的東西)。 批量修改函數(shù)名可直接使用sed

2. -fvisibility=hidden -- 最安全最推薦的做法

現(xiàn)在C/C++這一塊有幾十年的歷史,該踩的坑大家都應(yīng)該踩過去了。gcc編譯器就直接提供-fvisibility=hidden編譯選項(xiàng),直接讓庫函數(shù)global可見變成local可見, 使用__attribute__((visibility("default")))直接將需要的函數(shù)暴漏在外面就行

-fvisibility=[default|internal|hidden|protected]
Set the default ELF image symbol visibility to the specified option---all symbols are marked with this unless overridden within the code. Using this feature can very substantially improve linking and load times of shared object libraries, produce more optimized code, provide near-perfect API export and prevent symbol clashes. It is strongly recommended that you use this in any shared objects you distribute.
A good explanation of the benefits offered by ensuring ELF symbols have the correct visibility is given by "How To Write Shared Libraries" by Ulrich Drepper (which can be found at <http://www.akkadia.org/drepper/>)---however a superior solution made possible by this option to marking things hidden when the default is public is to make the default hidden and mark things public.

     將默認(rèn)ELF符號(hào)可見性設(shè)置為指定選項(xiàng)---除非在代碼中覆蓋,否則所有符號(hào)都標(biāo)記為此。 使用此功能可以極大地改善共享對(duì)象庫的鏈接和加載時(shí)間,生成更優(yōu)化的代碼,提供近乎完美的API導(dǎo)出并防止符號(hào)沖突。 強(qiáng)烈建議您在分發(fā)的任何共享對(duì)象中使用它
     Ulrich Drepper的“如何編寫共享庫”(可在<http://www.akkadia.org/drepper/>上找到)中給出了確保ELF符號(hào)具有正確可見性所帶來的好處的一個(gè)很好的解釋 - - 當(dāng)默認(rèn)為公共時(shí),通過此選項(xiàng)可以標(biāo)記隱藏的內(nèi)容的優(yōu)秀解決方案是隱藏默認(rèn)值并將事物標(biāo)記為公共

四、練習(xí)實(shí)踐---驗(yàn)證動(dòng)態(tài)庫的同名函數(shù)調(diào)串

1.代碼結(jié)構(gòu)很簡單
.  
├── libqqmusic.c              
├── libtmemusic.c              
├── main
├── main.c
├── makefile
└── README.md
2. libqqmusic.c
//libqqmusic.c

#include<stdio.h>

int get_music_id()
{
    return 1111;
}

void qqmusic_print()
{
    printf("qqmusic id: %d\n", get_music_id());

    return;
}
3. libtmemusic.c
//libtmemusic.c

#include<stdio.h>

int get_music_id()
{
    return 2222;
}

void tmemusic_print()
{
    printf("tmemusic id: %d\n", get_music_id());

    return;
}
4. main.c
//main.c

#include<stdio.h>

int main(int argc, char *argv[])
{

    printf("start\n");

    tmemusic_print();

    qqmusic_print();

    tmemusic_print();

    printf("end\n");

    return 0;
}
5.makefile
# 1. create  /etc/ld.so.conf.d/vaynedu-test.conf
#         /usr/lib64/vaynedu
# 2. mkdir /usr/lib64/vaynedu 
#
# 3. \cp *.so /usr/lib64/vaynedu

all:
    gcc -g -fpic -c -o libqqmusic.o libqqmusic.c
    gcc -g -shared -o libqqmusic.so libqqmusic.o 
    gcc -g -fpic -c -o libtmemusic.o libtmemusic.c
    gcc -g -shared -o libtmemusic.so libtmemusic.o
    \cp *.so /usr/lib64/vaynedu
    @ldconfig
    #gcc -g -o main main.c -L. -lqqmusic -ltmemusic
    gcc -g -o main main.c -L. -ltmemusic -lqqmusic
    @echo -e "\n\ncompile complete\n\n"

clean:
    rm -fr *.so *.o
6.測(cè)試結(jié)果--證明同名函數(shù)庫受編譯時(shí)加載順序的影響

將tmemusic放在前面gcc -g -o main main.c -L. -ltmemusic -lqqmusic
記錄一次采坑--如何處理Linux動(dòng)態(tài)庫同名函數(shù)?
將qqmusic放在前面gcc -g -o main main.c -L. -lqqmusic -ltmemusic
記錄一次采坑--如何處理Linux動(dòng)態(tài)庫同名函數(shù)?

五、總結(jié)

《程序的自我修養(yǎng)-鏈接、裝載與庫》應(yīng)該好好的啃一遍, 這個(gè)一個(gè)后臺(tái)開發(fā)必備的知識(shí)技能

-fvisibility=hidden的用法 https://blog.csdn.net/caspiansea/article/details/77113066
多共享動(dòng)態(tài)庫中同名對(duì)象重復(fù)析構(gòu)問題的解決方法 https://www.ibm.com/developerworks/cn/linux/l-cn-sdlstatic/
GCC的符號(hào)可見性——解決多個(gè)庫同名符號(hào)沖突問題 http://blog.chinaunix.net/uid-27875-id-5759441.html

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。

當(dāng)前名稱:記錄一次采坑--如何處理Linux動(dòng)態(tài)庫同名函數(shù)?-創(chuàng)新互聯(lián)
網(wǎng)頁網(wǎng)址:http://muchs.cn/article40/dejdho.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供服務(wù)器托管、手機(jī)網(wǎng)站建設(shè)、網(wǎng)站營銷、網(wǎng)頁設(shè)計(jì)公司網(wǎng)站導(dǎo)航、品牌網(wǎng)站設(shè)計(jì)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

營銷型網(wǎng)站建設(shè)