靜態鏈接庫和動態鏈接庫(隱式載入顯式載入)

文章目錄

  • 動態鏈接庫和靜態鏈接庫
    • 什么是鏈接庫?
    • 靜態鏈接庫
    • 動態鏈接庫
    • 動態鏈接庫的倆種鏈接方式
      • 加載時動態鏈接
      • 運行時動態鏈接

動態鏈接庫和靜態鏈接庫

動態鏈接庫和靜態鏈接庫都是共享代碼的方法,只是二者略有區別。

以C/C++為例,一個可執行文件的生成主要包括預編譯、編譯、匯編和鏈接。而靜態鏈接和動態鏈接就是 在鏈接階段的倆種處理。
在這里插入圖片描述

什么是鏈接庫?

關于代碼復用,有些文件專門用于存儲可以重復使用的代碼塊,例如功能實用的函數或者類,我們通常將它們稱為庫文件,簡稱“庫”(Library)。將這種庫文件進行打包編譯后得到二進制文件就是鏈接庫。

鏈接庫是一個不能獨立運行的二進制文件,它必須經過其他程序調用,才可以載入內存中。

根據鏈接方式的不同,可以分為靜態鏈接庫動態鏈接庫

靜態鏈接庫

所謂靜態鏈接,就是在程序執行前,將所有目標文件同靜態鏈接庫一起組織成可執行文件,這樣生成的可執行文件可以獨立運行

采用靜態鏈接庫的方式共享代碼有一個明顯的缺點,那就是文件的體積會很大,因為可執行文件包含了所有目標文件和靜態鏈接庫的數據。這樣容易造成內存空間的浪費。同時,不利用代碼的模塊化:如果有某個模塊需要更新,整個程序都需要重新連接才能運行。

若是有多個程序調用相同函數,內存中就會存在這個函數的多個拷貝。

動態鏈接庫

動態鏈接是相對靜態鏈接而言的,動態鏈接所調用的代碼并沒有被打包到可執行文件中,被拷貝的往往只是某些函數的描述信息(如重定位信息),只有當程序執行的過程中,需要調用到動態庫中的函數式,動態鏈接庫中的函數才會被載入內存中。

一般情況下,一個程序如果使用了動態鏈接庫,系統會保證內存中只有一份DLL的復制品。

動態鏈接庫可以隨可執行文件一同載入內存,也可以在可執行文件運行過程中載入,即可執行文件什么時候需要,動態鏈接庫才會載入內存。

采用動態鏈接庫方便程序的更新,當程序的某個模塊更新后,只需要將舊的模塊替換掉,程序運行時會自動將所有模板載入內存并動態地鏈接在一起。

但是動態鏈接庫也有一定的缺點,靜態鏈接生成的可執行文件能夠在其他同類操作系統上直接運行。但是如果是動態鏈接生成的文件,在移植到其他操作系統上后,需要連同該可執行文件所調用到的DLL文件一并拷貝過去,不然不能保證程序的正常運行。

動態鏈接庫的倆種鏈接方式

動態鏈接實際上還有倆種不同的連接方式:加載時動態鏈接和運行時動態鏈接(隱式加載顯式加載

加載時動態鏈接

在加載時動態鏈接中,應用程序像本地函數一樣顯式調用導出的 DLL 函數。要使用加載時動態鏈接,請在編譯和鏈接應用程序時提供頭文件 (.h) 和導入庫 (.lib) 文件。執行此操作時,鏈接器將為系統提供加載 DLL 所需的信息,并在加載時解析導出的 DLL 函數位置。

使用加載時動態鏈接,同靜態鏈接有一個相同的缺點,那就是如果程序的體積稍大,程序開始時加載的時間就會過長。

加載時動態鏈接和靜態鏈接的區別:

  • 鏈接的時機:加載時動態鏈接是在程序加載時程序才會將動態庫載入到內存中,而靜態鏈接則是在編譯的時候就已經將靜態庫的代碼和數據嵌入到可執行文件中了。

正如上面所說的,使用加載時動態鏈接,需要提供頭文件 (.h) 和導入庫 (.lib) 文件。可以直接在源碼中引入.lib文件。

例如:

#pragma comment(lib, "dllDemo.lib")

為了更好的模塊化設計,也可以將lib中所要用到函數聲明放在頭文件中。

例如:

//dllDemo.h
#ifndef _DLLDEMO_H
#DEFINE _DLLDEMO_H#pragma comment(lib,"dllDemo.lib")
_declspec(dllexport) int add(int, int);
_declspec(dllexport) int sub(int, int);#endif

之后的主程序中記得

#include "dllDemo.h"

上述代碼還用了_declspec(dllimport) 標識符聲明函數來自動態鏈接庫。

運行時動態鏈接

在運行時動態鏈接中,應用程序調用LoadLibrary 函數或LoadLibraryEx 函數在運行時加載DLL。 DLL成功加載后,可以使用GetProcAddress函數獲取要調用的導出DLL函數的地址。當您使用運行時動態鏈接時,不需要導入庫文件。

LoadLibrary 函數的作用是將指定的模塊加載到調用進程的地址空間中。

函數定義:

HMODULE LoadLibraryA([in] LPCSTR lpLibFileName //模塊的名稱。這可以是庫模塊(.dll 文件)也可以是可執行模塊(.exe文件)
);

如果調用成功,將會返回該模塊的句柄。

當得到該模塊的句柄后,可以使用GetProcAddress函數,它從指定的動態鏈接庫 (DLL) 檢索導出函數(也稱為過程)或變量的地址。

函數原型:

FARPROC GetProcAddress([in] HMODULE hModule, //該模塊的句柄[in] LPCSTR  lpProcName  //函數或變量的名稱
);

如果調用成功,則返回導出函數或變量的地址。

示例:

#include <windows.h>int main() {// 加載動態鏈接庫HMODULE hLibrary = LoadLibrary("example.dll");if (hLibrary != NULL) {// 獲取函數地址FARPROC functionAddress = GetProcAddress(hLibrary, "exampleFunction");if (functionAddress != NULL) {// 調用動態鏈接庫中的函數typedef void (*FunctionType)();FunctionType myFunction = (FunctionType)functionAddress;myFunction();}// 卸載動態鏈接庫FreeLibrary(hLibrary);}return 0;
}

以上關于運行時動態鏈接的實例是基于Windows的,如果是在linux上使用運行時動態鏈接,則需要通過使用 dlopendlsym以及 dlclose函數。

實例:

#include <dlfcn.h>int main() {// 加載動態鏈接庫void* libraryHandle = dlopen("libexample.so", RTLD_LAZY);if (libraryHandle != NULL) {// 獲取函數地址void (*myFunction)() = (void (*)())dlsym(libraryHandle, "exampleFunction");if (myFunction != NULL) {// 調用動態鏈接庫中的函數myFunction();}// 卸載動態鏈接庫dlclose(libraryHandle);}return 0;
}
參考
https://learn.microsoft.com/en-us/troubleshoot/windows-client/deployment/dynamic-link-library
https://c.biancheng.net/dll/what_is_library.html
https://blog.csdn.net/fuzhongmin05/article/details/54616520
https://blog.csdn.net/u010154760/article/details/45689899?spm=1001.2014.3001.5502

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/215176.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/215176.shtml
英文地址,請注明出處:http://en.pswp.cn/news/215176.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

工作中用到的數通、安全的查詢、工具、文檔鏈接

文章目錄 一、華為1.設備信息查詢華為序列號查詢華為設備信息速查 2.維護華為交換機命名規則查看光模塊信息交換機ping參數大全 3.實用文檔智能升級堆疊重啟指定成員設備堆疊主備倒換策略路由實現多出口重定向下一跳vrf與vrf、vrf與public互訪路由配置總結 二、奇安信1.授權申請…

四十五----組件庫設計

組件庫設計主要考慮幾點。 有意義: 命名準確,充分表意。參數準確,必要的類型檢查。適當的注釋 通用性:不要耦合特殊的業務功能。不要包含特定的代碼處理邏輯。 ?狀態,?副作?:狀態向上層提取,盡量少?內部狀態。解耦IO操作。 避免過度封裝:合理冗余。避免過度抽象。 …

Rust 學習

Rust 官網&#xff1a;https://www.rust-lang.org/zh-CN/ 1、Rust 簡介 Rust 是一門注重安全&#xff08;safety&#xff09;、速度&#xff08;speed&#xff09;和并發&#xff08;concurrency&#xff09;的現代系統編程語言。Rust 通過內存安全來實現以上目標&#xff0c;但…

LintCode 123 · Word Search (DFS字符處理經典題!)

123 Word Search Algorithms Medium Description Given a 2D board and a string word, find if the string word exists in the grid. The string word can be constructed from letters of sequentially adjacent cell, where “adjacent” cells are those horizontally o…

arcgis api for js4.x 圖層要素的增刪改---使用服務地址的/applyEdits直接進行刪除

添加新要素到圖層 _addGeo(){cosnt self thislet url https://......./featurelayer/某某某圖層/3let geo 你新繪制的圖形let attributes 你新繪制圖形的屬性信息let addingGraphics Graphic({geometry:geo,attributes:attributes})const pro self._addToLayer(url , JS…

Day57力扣打卡

打卡記錄 最小體力消耗路徑 鏈接 Dijkstra 將Dijkstra算法從計算最短路徑轉化為計算路徑最大差值。 class Solution:def minimumEffortPath(self, heights: List[List[int]]) -> int:n, m len(heights), len(heights[0])dist [0] [0x3f3f3f3f] * (n * m - 1)vis set…

iPhone 數據恢復:iMyFone D-Back iOS

iMyFone D-Back iOS 最佳 iPhone 數據恢復&#xff0c;最好的 iPhone 數據恢復軟件&#xff0c;恢復成功率最高。 直接從iOS設備、iTunes/iCloud/第三方程序備份快速恢復數據。 有選擇地恢復已刪除的照片、WhatsApp、消息和 18 多種其他數據類型。 僅通過 iCloud 帳戶訪問即可從…

關系型數據庫-SQLite介紹

優點&#xff1a; 1>sqlite占用的內存和cpu資源較少 2>源代碼開源&#xff0c;完全免費 3>檢索速度上十幾兆、幾十兆的數據庫sqlite很快&#xff0c;但是上G的時候最慢 4>管理簡單&#xff0c;幾乎無需管理。靈巧、快速和可靠性高 5>功能簡…

如何設定一個N層CNN的Layer,CNN初始化

如何設定一個N層CNN的Layer&#xff0c;CNN初始化 前言干貨代碼解釋 結語 前言 目前人工智能已經融入到我們的生活&#xff0c;大數據模型也是層出不窮。那我們就學習一些簡單的模型設置。 干貨 代碼 # This is the original CNN layer setup, def build_cnn(input_layer):…

Vue router深入學習

Vue router深入學習 一、單頁應用程序介紹 1.概念 單頁應用程序&#xff1a;SPA【Single Page Application】是指所有的功能都在一個html頁面上實現 2.具體示例 單頁應用網站&#xff1a; 網易云音樂 https://music.163.com/ 多頁應用網站&#xff1a;京東 https://jd.co…

springboot打成war包及VUE打成war包放入tomcat啟動

1.springboot打成war包步驟 首先在springboot啟動類中繼承SpringBootServletInitializer&#xff0c;重寫configure方法&#xff0c;如下: SpringBootApplication() public class StartApplication extends SpringBootServletInitializer {public static void main(String[] …

Java與.Net的區別

Java 和 .NET 是兩個不同的軟件開發平臺&#xff0c;它們在語言、生態系統、跨平臺性和開發工具等方面有著不同的特點。 1. 語言&#xff1a;Java 使用 Java 編程語言&#xff0c;而 .NET 使用 C#、VB.NET、F# 等多種編程語言。Java 是一種面向對象的編程語言&#xff0c;它強…

在gen_server使用ets實例演示

Erlang的ETS&#xff08;Erlang term storage&#xff09;是一種在內存中存儲數據的結構&#xff0c;類似于其他語言中的數據庫。它允許你在Erlang程序中存儲和檢索數據。gen_server是Erlang中用于創建服務器的一種模式&#xff0c;它能夠處理并發的客戶端請求。 以下是在gen_…

大數據技術10:Flink從入門到精通

導語&#xff1a;前期入門Flink時&#xff0c;可以直接編寫通過idea編寫Flink程序&#xff0c;然后直接運行main方法&#xff0c;無需搭建環境。我碰到許多初次接觸Flink的同學&#xff0c;被各種環境搭建、提交作業、復雜概念給勸退了。前期最好的入門方式就是直接上手寫代碼&…

[滲透測試學習] CozyHosting - HackTheBox

文章目錄 信息搜集 信息搜集 nmap掃描一下&#xff0c;發現存在80端口和22端口 nmap -sV -sC -p- -v --min-rate 1000 10.10.11.230直接訪問80端口發現有跳轉 那么我們將ip添加到hosts里面&#xff0c;成功訪問 觀察發現是企業網站&#xff0c;掃描一下沒有子域名 那么就掃…

【后端學前端】第二天 css動畫 動感菜單(css變量、過渡動畫、過渡延遲、js動態切換菜單)

目錄 1、學習信息 2、源碼 3、變量 1.1 定義變量 1.2 使用變量 1.3 calc() 函數 4、定位absolute和fixed 5、transform 和 transition&#xff0c;動畫 5.1 變形transform 5.2 transition 5.3 動畫animation 6、todo 1、學習信息 視頻地址&#xff1a;css動畫 動感菜…

【jenkins操作步驟】

一、安裝ant 1、下載安裝文件 1.1 進入https://ant.apache.org/ 然后點擊 https://ant.apache.org/bindownload.cgi 超連接下載即可 1.2下載到本地&#xff0c;最好放到D盤下&#xff0c;然后把apache-jmeter-4.0\extras目錄下的ant-jmeter-1.1.1.jar 文件放置到ant下的lib目…

Java最全面試題專題---2、Java集合容器(1)

集合容器概述 什么是集合 **集合框架&#xff1a;**用于存儲數據的容器。 集合框架是為表示和操作集合而規定的一種統一的標準的體系結構。 任何集合框架都包含三大塊內容&#xff1a;對外的接口、接口的實現和對集合運算的算法。 **接口&#xff1a;**表示集合的抽象數據類…

開箱即用的C++決策樹簡單實現

一個數據結構期末作業&#xff08;有興趣用的話可以高抬貴手star下?~&#xff09;GitHub - mcxiaoxiao/c-Decision-tree: 決策樹c簡單實現 &#x1f333; c-Decision-tree 附大作業/課設參考文檔.doc &#x1f333; c-Decision-tree Introduction &#x1f64c; c-Decision…

[c++]—vector類___基礎版(帶你了解vector熟練掌握運用)

&#x1f469;&#x1f3fb;?&#x1f4bb;作者:chlorine 目錄 &#x1f393;標準庫類型vector &#x1f393;定義和初始化vector的對象 &#x1f4bb;列表初始化vector對象 &#x1f4bb;創建指定數量的元素 &#x1f576;?值初始化 ?列表初始化還是值初始化&#xf…