装入归档文件时出现了一个错误linux_静态链接与动态链接(Linux)

前言

上一篇分享了静态链接与动态链接的实验(Windows下)。这一篇分享Linux下的笔记,同时对上一篇笔记做一个补充。

首先,我们把静态链接与动态链接做一个这样子的比喻:

把链接过程看做我们平时学习时做笔记的过程。我们平时学习时准备一本笔记本专门记录我们的学习笔记,比如在某本书的某一页上看到一个很好很有用的知识,这时候我们有两种方法记录在我们的笔记本上,一种是直接把那一页的内容全部抄写一遍到笔记本上(静态链接);另一种是我们在笔记本上做个简单的记录(动态链接),比如写上:xxx知识点在《xxx》的xxx页。

从这两种方法中我们可以很清楚地知道两种方式的特点,第一种方式的优点就是我们在复习的时候就很方便,不用翻阅其它书籍了,但是缺点也很明显,就是占用笔记本的空间很多,这种方法很快就把我们的笔记本给写满了。第二种方式的优点就是很省空间,缺点就是每当我们复习的时候,手头上必须备着相关的参考书籍,比如我们去教室复习的时候,就得背着一大摞书去复习,这样我们复习的效率可能就没有那么高了。

这对应到我们的动态链接与静态链接上是不是就很好理解了:

静态链接与动态链接的主要优缺点

(1)静态链接的优缺点:

优点:

  • 代码装载速度快,执行速度略比动态链接库快;

缺点:

  • 使用静态链接生成的可执行文件体积较大,包含相同的公共代码,造成浪费。

(2)动态链接的优缺点:

优点:

  • 生成的可执行文件较静态链接生成的可执行文件小;

缺点:

  • 速度比静态链接慢;

动态、静态链接实验

我们先编写如下代码(共三个文件):

文件1(main.c):

#include "test.h"​void print_hello(void){    printf("hello world");}

文件2(test.c):

#ifndef __TEST_H#define __TEST_H​#include ​void print_hello(void);​#endif

文件3(test.h):

#ifndef __TEST_H#define __TEST_H#include void print_hello(void);#endif

1、动态链接实验

首先,将源文件生成目标文件(*.o),命令:

gcc -c -fPIC main.c test.c

这里得根据实际编译环境加上或者不加上-fPIC参数,这个是与gcc的版本有关,像我这边的gcc 5.4.0就得显示加上-fPIC这个参数,若是不加,则会影响下一步的链接过程。

8d9b98090b4b7cfbfd3e4175b5f7aec6.png

在Linux中,动态库的扩展名一般为.so。针对上面生成的test.o文件,生成动态库的命令为:

gcc -shared test.o -o libtest_d.so
4a392dfc5b65edf05853c778f5d69cfc.png

若是上一步不加-fPIC参数,则会产生如下错误:

9595fa297cf6f8e99d0ffeb8336ea16b.png

大概意思就是.rodata不可以拿来制作共享文件,请加上-fPIC参数重新编译。问题分析:

-fPIC 作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code),则产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。

从gcc来看,shared应该是包含fPIC选项的,但似乎不是所有的版本都支持,所以最好显式加上fPIC选项。

使用链接动态库的方式生成可执行程序,命令:

gcc main.o -L. -ltest_d -o test_d.out
1c7434eff28cda2fc3e17d122a16209b.png

这里的-L.的含义是在搜索库文件时包含当前目录,-ltest_d的含义是链接名称为libtest_d.so的动态链接库。

下面运行test_d.out程序,发现出现如下错误:

c58df08f4da89d4ccb4a6a49d0f8723c.png

不能找到共享库文件libtest_d.so,加载失败。因为一般情况下Linux会在/usr/lib路径中搜索需要用到的库,而libtest_d.so库并不在这个路径下。解决方法有两种:一种就是把这个文件拷贝至/usr/lib路径下,但是一般不允许这样做,一般用户也不允许往这个路径里拷贝东西。另一种就是把当前路径增加为动态库的搜索路径,命令为:

export LD_LIBRARY_PATH=./:$LD_LIBRARY_PATH

这时候就可以正常运行了:

ba3326c7da9637c100d2392eca38bf6d.png

2、静态链接实验

静态库用ar工具来制作。ar是一个归档工具,用于建立、修改、提取归档文件(archive)。一个归档文件可以包含多个目标文件,也被称为静态库。在Linux下,静态库的扩展名一般为.a。

把目标文件test.o做成静态库,命令:

ar -rv libtest_s.a test.o
9c6a3532c23d5134d5056f773c3a7bd4.png

其中rv参数为组合参数,其中r参数表示当建立的模块名已经存在时,则覆盖同名模块,v参数用来显示附加信息,比如被处理的文件的名字。

使用链接静态库的方法生成可执行程序,命令:

gcc main.o -L. -ltest_s -o test_s.out
2f858990a827e923206a9b63bda1bdf4.png

运行程序:

3d3d6a37321e17ef8b46820e1ca7b034.png

删除静态库之后,可执行程序也是能正常运行的。事实上,使用链接静态库的方式生成的可执行程序与直接使用目标文件生成的可执行程序没有区别。只是经过了静态库的链接,变为了一个文件,方便于调用、移植和保存。

归档工具ar可以很方便地查看和删除归档文件中的成员。

查看静态库libtest_s.a中的内容,命令:

edd75ebdab6cb09de8a76e01fd24eaf9.png

关于ar工具更多的命令参数可输入ar --help进行查看:

42677f28f5a51108ecc850fa68106f11.png

以上就是关于静态链接与动态链接的Linux笔记,如有错误,欢迎指出!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/489200.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c++ object model

对一个结构体进行不断的封装后可以形成一个c类,为此需要添加很多函数成员之类的代码,为此显示c比c语言显得庞大并且迟缓,但是事实并不是这些 c在布局和时间上的额外承担主要是由virtual引起的 下面简述c对象模型 数据成员包括静态成员和非静态…

9008刷机怎么刷_OV快捷进入高通进9008或fastboot模式刷机解锁,和MTK关机解锁

不喜略过。高通进9008刷机解锁:关机状态下,同时按音量下键上键插线进9008 .(注意安装手机驱动)高通进fastboot模式解锁:旧机型(平台上选择不到机型的)进fast解锁,关机状态 音量下键开机键 MTK关机解锁:关机状态下按音量上键&#…

10年内,19个关键技术将改变世界

来源: 科技联盟技术中心据国外媒体报道,从无人驾驶汽车到机器人工人,在我们熟悉所有这一切之前,未来正迎面走来。根据世界经济论坛全球议程理事会关于《未来软件与社会》的一份报告,到2025年前,很多新兴技术…

scope参数错误或没有scope权限_SSM 单体框架 - 前端开发:用户和权限模块

用户管理分页 & 条件查询用户数据查询条件1. 用户手机号 2. 注册时间,包含开始日期和结束日期日期选择器组件在查询条件中使用了 Element UI 中的日期选择器:https://element.eleme.cn/#/zh-CN/component/date-picker#mo-ren-xian-shi-ri-qi在测试项目中创建一个…

武器化道路越走越远的无人机

来源:雷擎科技在数以千计的军用无人机中,绝大部分都用于监视。国防专家预测这种情况将会一直存在。Janes的分析师预计,在未来10年内,全球将购买超过80,000架监视无人机和近2,000架攻击无人机。武器化的无人机并不便宜。专家表示&a…

怎样查看cudnn版本_ubuntu16.04+Geforce GTX1060安装CUDA和cuDNN

DELL G7系列,ubuntu16.04,本机显卡型号: GeForce GTX 1060。主要步骤如下:一,安装NVIDIA驱动。1,本笔记本是F12进入BIOS,将secure boot设置为disable。2,通过下面命令确保电脑上之前的nvidia驱动…

Unity3DGUI:Window

#pragma strictvar winRect:RectRect(30,100,150,200);var windowShow:booleantrue;function OnGUI () { windowShowGUI.Toggle(Rect(10,10,100,20),windowShow,"窗口显示"); if(windowShow) //参数:windowID,位置,回调函数&#x…

android分享文件分享结果_干货分享丨DM删除归档日志文件的多种方法

上一期我们讲解了DM数据库归档日志的切换,本期我们讲解DM数据库归档日志文件的删除。本章内容已在如下环境上测试:①操作系统:中标麒麟7;②数据库版本:达梦8;相关关键字:DM数据库、归档日志文件…

三个维度看全球半导体格局变迁

来源:世纪证券费城半导体指数(SOX) 的发展阶段反应了全球半导体的走势与兴衰更替。费半指数涵盖全球半导体设计、设备、制造、 材料等方向, 其走势可以是衡量全球半导体行业景气程度的主要指标。费城半导体指数发行于在 1993 年12…

alot英文怎么读_很多的英文怎么说

你知道吗?一起来学习一下吧!很多的英文:可数:a lot of, lots of, many不可数:a good/great deal of , a good/ great amount of两者皆可:a large quantity of, quantities of同义词辨析:a lot of 和 lots of &#xf…

用samba来创建windows下的文件共享

前言 Samba是一个能让Linux系统应用Microsoft网络通讯协议的软件,而SMB是Server Message Block的缩写,即为服务器消息块 ,SMB主要是作为Microsoft的网络通讯协议,后来Samba将SMB通信协议应用到了Linux系统上,就形成了现…

go 微服务框架_清晰架构(Clean Architecture)的Go微服务

更新我最进对这个框架进行了重大升级,虽然所做的改动不大,但成效显著。这次更新修复了旧框架中的所有主要问题,尽管它的的主要项目结构和接口都没有改变,具体改动内容请参见清晰架构(Clean Architecture)的…

贝叶斯网络之父Judea Pearl力荐、LeCun点赞,这篇长论文全面解读机器学习中的因果关系...

来源:机器之心作者:Bernhard Schlkopf图灵奖得主、贝叶斯网络之父 Judea Pearl 曾自嘲自己是「AI 社区的反叛者」,因为他对人工智能发展方向的观点与主流趋势相反。Pearl 认为,尽管现有的机器学习模型已经取得了巨大的进步&#x…

了解Web及网络基础——《图解http》第一章

1. 现在已提出的三项WWW构建技术,分别是把SGML作为页面的文本标记语言的HTML;作为文档传递协议的HTTP;指定文档所在地址的URL(统一资源定位符)。* 2. 网络基础:TCP/IP。通常使用的网络是在TCP/IP协议族的基…

python中如何连接两个字符串_python字符串连接的N种方式总结

python中有很多字符串连接方式,今天在写代码,顺便总结一下:最原始的字符串连接方式:str1 str2python 新字符串连接语法:str1, str2奇怪的字符串方式:str1 str2% 连接字符串:‘name:%s; sex: %…

tomcat防cc_浅析Tomcat防止资料被锁的方式

在Windows平台的Tomcat上部署应用后,应用下的个别文件可能会被Tomcat锁住,解部署的时候删除不掉那些内容,就会导致无法重部署。如果解部署删除不掉被锁的文件,Tomcat会在日志中警告说:2013-1-9 15:44:09 org.apache.ca…

python怎么发送微信给自己_Python新手教程:Python微信定时自动给【女朋友】发送天气预报...

效果图主要思路1.从wxpy获取好友列表2.创建定时器3.定时器触发函数4.函数执行,遍历好友列表5.好友对象执行带参函数,参数为该好友城市6.函数中请求百度天气接口,得到该好友对应天气数据,解析处理数据,发送天气信息&…

Science子刊带来新遗传证据:早期人类驯化了自己

来源:中国生物技术网在开始驯化狗、猫、绵羊和牛等动物前,人类可能已经有了驯化一种完全不同动物的传统,就是我们人类自己。近日,发表在《Science Advances》上的一项新研究引用从某种程度上反映驯化元素的一种疾病的遗传证据表明…

简单的HTTP协议——《图解http》第二章

2.1 HTTP协议用于客户端和服务端直接的通信 在一条通信线路上必定一端是客户端,另一端则是服务端。 2.2 通过请求和响应的交换达成通信。 HTTP协议规定,请求从客户端发出,最后服务器响应该请求并返回。 请求报文的构成和解读。 请求报文是由请…

nacicat for mysql查询_navicat for mysql怎么用

navicat简单的使用方法:1、创建数据库:选中连接名,右键,点击新建数据库。2、删除数据库:选中要删除的数据库,右键,点击删除数据库。3、创建数据表:双击test01,选中表,右键…