中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

記錄一次采坑--如何處理Linux動態庫同名函數?

發布時間:2020-05-30 00:29:32 來源:網絡 閱讀:1111 作者:vaynedu 欄目:編程語言

一、背景介紹

需求描述:業務提供一個鑒權的靜態庫,我只需要從url 和 參數中提取相應的參數傳給業務的靜態庫,將靜態庫的處理結果直接返回給業務(return < 0, 直接返回403)。

但是最近業務反饋,請求部分url直接返回Error:-1015錯誤,不符合預期。

二、分析過程

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

  1. 讓業務檢查配置 ,是否和校驗級別有關系?
  2. 雙方md5的靜態庫,本地調試結果是否正確?
  3. 上述方案不行: 采用最挫的方案, 既然靜態庫吐出來的結果,瘋狂加printf,我就不信這個邪了

最后還是走到方案3,業務說printf的結果不符合預期,經業務提醒,突然意識到是不是調用鏈接到其他庫的xx_func?

因為項目比較大, 涉及的庫比較多,我用nm認真檢查了編譯時加載的庫,竟然還真找到一模一樣的接口xx_func

nm   ./lib/liba.a | grep xx_func

記錄一次采坑--如何處理Linux動態庫同名函數?
編譯代碼的時候,趕緊去掉了同名函數庫(因為在makefile文件編譯的時候某些公共庫默認都會編譯進去)。重新編譯版本。

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

隨手直接 nm *.so | grep xx_func,結果在另外一個so(暫時命名2.so)中,發現了同名函數xx_func。 看了一下配置,程序啟動的時候首先加載了2.so動態庫, 1.so是在2.so后面加載的. 因為優先加載哪個庫,就使用哪個庫的同名函數,并不會覆蓋的情況(自己現網測試 + 測試代碼)

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

三、解決方案

1. 最簡單的方案 -- 修改函數名稱

因為業務本身提供的靜態庫,用nm查看函數也不多,為了安全起見,修改每個函數的名稱(增加一些業務私有的東西)。 批量修改函數名可直接使用sed

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

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

-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.

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

四、練習實踐---驗證動態庫的同名函數調串

1.代碼結構很簡單
.  
├── 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.測試結果--證明同名函數庫受編譯時加載順序的影響

將tmemusic放在前面gcc -g -o main main.c -L. -ltmemusic -lqqmusic
記錄一次采坑--如何處理Linux動態庫同名函數?
將qqmusic放在前面gcc -g -o main main.c -L. -lqqmusic -ltmemusic
記錄一次采坑--如何處理Linux動態庫同名函數?

五、總結

《程序的自我修養-鏈接、裝載與庫》應該好好的啃一遍, 這個一個后臺開發必備的知識技能

-fvisibility=hidden的用法 https://blog.csdn.net/caspiansea/article/details/77113066
多共享動態庫中同名對象重復析構問題的解決方法 https://www.ibm.com/developerworks/cn/linux/l-cn-sdlstatic/
GCC的符號可見性——解決多個庫同名符號沖突問題 http://blog.chinaunix.net/uid-27875-id-5759441.html

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

松滋市| 墨脱县| 乌兰察布市| 资溪县| 偏关县| 紫金县| 武夷山市| 玉环县| 岢岚县| 平顶山市| 罗定市| 连平县| 玉林市| 东平县| 西宁市| 茶陵县| 乌拉特前旗| 阿鲁科尔沁旗| 衡山县| 康乐县| 称多县| 泗水县| 保德县| 龙口市| 安乡县| 瓮安县| 康保县| 广丰县| 慈溪市| 临泽县| 太谷县| 鹰潭市| 齐齐哈尔市| 永修县| 临汾市| 德清县| 江源县| 综艺| 甘谷县| 沂源县| 沿河|