從現在看,非操作系統(或平台)的軟體在動態鏈接時用二進位本機代碼,是一個錯誤嗎?
02-24
如果沒理解錯誤的話,題主是在問動態鏈接庫的存在是一個錯誤嗎?一定不是啊, 雖然動態庫有它的不足,但是動態庫的地位無可取代啊.
舉幾個例子:
1:比如user32.dll,如果改成靜態鏈接,那每一個使用user32.dll的應用程序,都要靜態鏈接一份user32.lib(是靜態庫,非導入庫), 這增加了模塊的體積2:動態庫更新方便,模塊重新編譯,其它模塊無需改動,這要是拋棄動態鏈接庫簡直不敢想像,微軟修復一個bug後,你就要重新編譯下自己的應用程序,災難3:使用動態庫,運行時可以節省物理內存的佔用,windows的dll代碼段是有copy on write機制的,如果你不運行時修改該dll的代碼段,那所有的應用程序都共用同一份二進位代碼,如果全部改成靜態鏈接,那就沒辦法共享了,內存中就會存在大量的冗餘模塊代碼,浪費...........
說著說著就覺得動態鏈接庫簡直是天才設計出來的,相比之下dll hell這種小問題,真是瑕不掩瑜,至於通過動態庫注入啊,劫持這些問題,無論你改成什麼機制,都無法避免.最後說一句,以上內容是基於自己的理解,難免有誤,希望各位聚聚指點動態鏈接主要的問題是所謂DLL hell,即二進位兼容的困難性,導致現在的操作系統一般會保留所有不同版本的動態鏈接庫,還有軟體選擇不把依賴庫安裝到系統目錄,還有docker這樣的技術,有種越來越活回去了的感覺。但也要看到動態鏈接積極的一面,首先二進位分發,不管是執行效率問題還是商業軟體保護的問題都是不可避免的,所以共享庫只有靜態鏈接和動態鏈接可選,而動態鏈接不僅縮減了磁碟空間的佔用,還保證了重要的庫文件可以及時更新,避免安全問題出現。而且,動態鏈接是Windows下應用程序保持對不同版本操作系統兼容的唯一選擇,比如Windows下應用程序本質上是通過動態鏈接來調用Windows API的。現在由於硬體的升級,互相調用有了更多選擇,比如WebService,但動態鏈接仍然是執行效率最高的,不過要權衡利弊。
錯在何處?
代碼講究復用,二進位也可以學一學嘛。另外錯誤到底是聚焦在動態鏈接還是在本地代碼上?Java雖然不是本地代碼,但也可以動態載入jar嘛不是一個錯誤。
除了樓上諸位的回答,我認為動態庫存在的意義還包括讓代碼/二進位文件與運行時(runtime)解綁。
我們以一個普通的 Hello world C語言程序舉例:如果不使用動態庫而單純使用靜態鏈接,你必須將本機上(Intel-64)的 glibc 和你的程序綁在一起才可以運行。但你將這個程序拿到其他地方運行時,如果當地的 glibc 的實現方式和你綁進去的不一樣,這個程序將完全不能運行; 但如果使用動態鏈接庫,這個程序至少可以保證在不同環境下調用為該環境編寫的glibc ,一定程度上解決了上述問題。啊感覺題主貌似沒怎麼學過計算機基礎課程啊。。回去補補課吧。。使用動態鏈接庫的優點請參考操作系統課程~
靜態鏈接庫與動態鏈接庫的優缺點 - JimYe的專欄 - 博客頻道 - CSDN.NET而且。。錯誤這個貌似不太對吧,不論使用什麼方案都是有利有弊,只不過利弊不同而已,錯誤這個詞不是很準確啊。。
看到問題急不可耐的搶答下,雖然可能不太嚴謹。
當然不是,動態鏈接庫(基本都是二進位的)現在的位置其實是:表面是使用不到,其實處處都在使用。題主如果細看系統的話會發現:
1. 在windows上,幾乎操作系統非常依賴於動態鏈接庫,一般是dll(從一般dll到COM/COM+),你敢不敢到系統的windows或者system下刪除幾個試試;2. 在linux上,也非常依賴各種so動態鏈接庫,你敢不敢去各種lib(/,/usr,/usr/lib)下刪除幾個試試。但是為什麼現在開發很少使用呢?其實是假象,雖然大家現在大多使用JAVA/.NET之類的語言,以及各種類似python、js、php等解釋性腳本語言,只是沒有直接在寫代碼時用到動態鏈接庫,其實可以說在執行時處處在調用動態鏈接庫,另外一般可以通過動態鏈接庫擴充這些語言的功能、或者配合這些語言。
不細說了,題主想具體了解的話可以學習下操作系統、系統調用,或者看看類似《COM本質輪》(前三章就好,能找到這本書的話)的書。
最後明確一下,二進位動態鏈接庫不僅不是錯誤,而且是我們軟體系統發展過程中不可或缺的自然過程。一看你就不玩爐石
推薦閱讀: