gcc报错 can not be used when making a shared object; recompile with -fPIC

article/2025/10/6 16:29:06
  • 问题1:gcc报错 can not be used when making a shared object; recompile with -fPIC

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

如果不加-fPIC,则加载.so文件的代码段时,代码段引用的数据对象需要重定位, 重定位会修改代码段的内容,这就造成每个使用这个.so文件代码段的进程在内核里都会生成这个.so文件代码段的copy.每个copy都不一样,取决于 这个.so文件代码段和数据段内存映射的位置.



不加fPIC编译出来的so,是要再加载时根据加载到的位置再次重定位的.(因为它里面的代码并不是位置无关代码)
如果被多个应用程序共同使用,那么它们必须每个程序维护一份so的代码副本了.(因为so被每个程序加载的位置都不同,显然这些重定位后的代码也不同,当然不能共享)
我们总是用fPIC来生成so,也从来不用fPIC来生成a.
fPIC与动态链接可以说基本没有关系,libc.so一样可以不用fPIC编译,只是这样的so必须要在加载到用户程序的地址空间时重定向所有表目.

因此,不用fPIC编译so并不总是不好.
如果你满足以下4个需求/条件:
1.该库可能需要经常更新
2.该库需要非常高的效率(尤其是有很多全局量的使用时)
3.该库并不很大.
4.该库基本不需要被多个应用程序共享

如果用没有加这个参数的编译后的共享库,也可以使用的话,可能是两个原因:
1:gcc默认开启-fPIC选项
2:loader使你的代码位置无关

修改cmake

set(extra_cmake_args)list(APPEND extra_cmake_args "-DCMAKE_CXX_FLAGS=-std=c++14 -w -fPIC")list(APPEND extra_cmake_args "-DCMAKE_C_FLAGS=-std=-w -fPIC")


或者

set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
  • 问题2: .bss .data can not be used when making a PIE object

å¨è¿éæå¥å¾çæè¿°

所以解决方案为

set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC -no-pie")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -no-pie")
  • 扩展:

ELF
Exucutable and Linkable Format,译为“可执行和可链接的格式”。
它是关于可执行文件、对象代码、共享库和内核导出的一种公共标准文件的格式定义,广泛应用于类unix系统。
每个ELF文件由三个部分组成:Program header table、Sectoin header table、Data referred to above。

PIC
Position-Independent Code,译为“位置无关代码”。
在计算机系统中,PIC是可以在主存中不同位置执行的目标代码。
PIC经常被用在共享库中,这样就能将相同的库代码为每个程序映射到一个位置,不用担心覆盖掉其他程序或共享库。

PIE
Position-Independent Executable,译为“位置无关可执行程序”。
它是完全由位置无关代码所组成的可执行二进制文件,有时可称为PIC Executable。
它有一个显著的优点,那就是当程序加载时,所有PIE二进制文件以及它所有的依赖都会加载到虚拟内存空间中的随机位置(随机地址),可以有效提高他人通过绝对地址实施"return-to-libc"安全攻击的难度。

GOT
Global Offset Table。全局偏移量表。
它是数据字段的地址存储表。它被可执行程序用于查看全局变量的运行时地址,这些变量的地址在编译阶段是未知的。
在进程引导阶段,动态链接器会更新GOT。

PLT
Procedure Linkage Table。过程链接表
它将位置无关的的函数调用转换为绝对地址。形象的比喻,PLT像蹦床一样,将对共享函数的调用弹向正确的方向。

Lasy Loading/Lasy Binding
延迟加载。
在位置无关代码PIC中一般不能包含动态链接库中符号的绝对地址。当运行某个调用动态库函数符号的用户态程序时,用户态程序在编译链接阶段并不知晓该符号的具体位置,只有等到运行阶段,动态加载器将所需要的共享库加载到内存后,才最终确定符号的地址。而在编译阶段所有与位置无关的函数调用都将被保存到ELF文件的过程链接表PLT(Procedure Linkage Table)中。


http://chatgpt.dhexx.cn/article/wTLgKXyC.shtml

相关文章

WRF——hdf编译报错 recompile with -fPIC

错误: 解决办法:重新编译zlib relocation R_X86_64_32 against .rodata can not be used when making a shared object; recompile with -fPIC 解决方案:以64位的方式重新编译zlib cd zlib CFLAGS"-fPIC" ./configure make …

mysql 存储过程 compile_SQLSERVER临时表导致存储过程重编译(recompile)的一些探讨_MySQL...

SQLSERVER为了确保返回正确的值,或者处于性能上的顾虑,有意不重用缓存在内存里的执行计划,而重新编译执行计划的这种行为,被称为重编译(recompile)。那么引发存储过程重编译的条件有哪一些呢?下面罗列了一些导致重编译…

mysql 存储过程 compile_SQL SERVER 临时表导致存储过程重编译(recompile)的一些探讨_MySQL...

SQLSERVER为了确保返回正确的值,或者处于性能上的顾虑,有意不重用缓存在内存里的执行计划,而重新编译执行计划的这种行为,被称为重编译(recompile)。那么引发存储过程重编译的条件有哪一些呢?下面罗列了一些导致重编译…

Qt recompile with -fPIC

Qt编译时提示: relocation R_X86_64_32 against ‘.rodata’ can not be used when making a PIE object: recompile with fPIC 于是百度, 找了很久找到一篇能够解决我这问题的帖子 在这里面的参考文档中提到,从Ubuntu16.10版本开始默认启用P…

IDEA安装JRebel实现热部署,自动reload和recompile

利用JRebel插件实现代码及时编译功能,帮助我们在开发过程中节省项目重启时间,提高开发效率。JRebel插件实现及时编译,帮助我们在开发过程中节省项目重启时间,提高开发效率。 一、安装 插件安装流程: 1.下载安装JRebel插…

WITH RECOMPILE和OPTION(RECOMPILE)区别

在考虑重编译T-SQL(或者存储过程)的时候,有两种方式可以实现强制重编译(前提是忽略导致重编译的其他因素的情况下,比如重建索引,更新统计信息等等),  一是基于WITH RECOMPILE的存储过程级别重编译,另外一种是基于OPTION(RECOMPILE)的语句级重编译。  之前了解的比较…

内网穿透群晖NAS:实现无公网IP远程访问群晖 2/2

系列文章 内网穿透群晖NAS:免费安装cpolar群晖套件 1/2内网穿透群晖NAS:实现无公网IP远程访问群晖 2/2 上一篇 内网穿透群晖NAS:免费安装cpolar群晖套件 1/2 在上一篇介绍里,我们在群晖系统中成功安装了图形化界面的cpolar&#…

群晖设置公网ipv6方式域名解析访问

1.环境说明 上网:电信光猫tplink路由器(电信送的) 群晖:DSM 7.1.1-42962 Update 2 域名服务商:腾讯云 2.光猫设置 2.1 获取光猫超级用户密码 拨打电信10000号 2.2 修改光猫为桥接模式 略 3.路由器设置 3.1 路由器拨号上网…

群晖 阿里云ddns_群晖QuickConnect功能详解

先来了解下什么是QuickConnect,这是群晖的一个远程访问功能, 有这个功能直接注册一个QuickConnect账号就可以远程访问了, 这样就不需要你的宽带是否有公网ip, 也不需要配置路由器端口映射, 就可以轻松的实现外网访问。 上图的 http://quickconnect.to/vip 外网在电脑浏览器…

IPv6/IPv4 + aliddns 实现黑群晖外网控制和访问

前言 一直想弄台黑群NAS,但因为穷!一直没入,一直用的是玩客云,但玩客云满足不了我的需求,但正好搭上蜗牛星际的车! J19004G内存16G固态4盘位千兆网口才380元,性价比是真的高,再买两…

群晖NAS配置DNSPodDDNS实现外网访问(仅适用于阿里云域名)

创作立场声明:本文只是单纯的经验分享,没有任何恰饭行为!转载前请联系作者授权,并附上此文章链接! 前言 本文将详解如何使用群晖NAS自带的DDNS功能来实现腾讯云DNSPod动态域名解析。 设置你的域名DNS服务器到DNSPod 登录阿里云控制台&…

【宇麦科技】腾xun云登场,群晖NAS自定义域名教程来啦~

如今网盘的使用成本越来越高,更多的人选择搭建自己的家庭 NAS 服务器。 NAS 可以用来做大容量存储、文件备份、文件下载、相册同步,甚至可以搭建网站、搭建自己的笔记以及邮件服务。 NAS 一般都安装在家里,那么出门在外应该如何远程访问家里的…

群晖NAS的公网、NAT、DDNS、证书等配置一

一、群辉NAS应用场景 你是否有过这样的需求? 1. 远程办公 日常的工作资料太多太杂乱,换个电脑根本没法工作?团队间资料共享太麻烦?Drive套件这个远程办公神器都能解决。 我的文件相当于远程的“我的文档”,“团队文件”是可以与团队成员共享。在PC端和手机端都可以方便…

群晖NAS教程(二十一)、利用Docker安装DDNS动态域名解析,自动更新域名解析到公网IP(支持阿里云、腾讯云dnspod、Cloudflare、华为云)

群晖NAS教程(二十一)、利用Docker安装DDNS动态域名解析,自动更新域名解析到公网IP(支持阿里云、腾讯云dnspod、Cloudflare、华为云) 为了更好的浏览体验,欢迎光顾勤奋的凯尔森同学个人博客http://www.huerpu.cc:7000 一、下载镜像与配置启动参数 在群…

群晖外网访问终极解决方法:IPV6+阿里云ddns+ddnsto

写在前面的话 受够了群晖的quickconnet的小水管了,急需一个新的解决方法,这是后发现移动没有公网IP,只有ipv6(公网的),时候有小伙伴要问,要是没有ipv6就没办法访问群晖了吗? 不&…

群辉默认DDNS功能解析阿里云-自定义服务商

前言 前不久买了个群辉NAS发现群辉DDNS不能解析阿里云,后来找了很多教程都是部署Docker或使用其他平台转发一下,然而这些平台还要注册,我就在想我自己可不可以实现不需要注册就可以使用的DDNS,毕竟咱也是干这个的。 然后我就去上…

一文搞懂“如何通过群晖+DNSPod DDNS搭建私有云服务?”

DNSPod春节特惠3折起 买解析就送CDN,最高60TB CDN让你带回家 👉🏻购买入口 近期很多DIY私有云玩家私聊D妹“我想在外网访问家庭网络,怎么搞?”,“如何将动态IP映射到一个固定的域名解析服务上?”…

[NAS] Synology (群晖) DSM7.0 使用自定义供应商DDNS

简介 找了很多教程都是部署Docker或使用其他平台转发一下,然而这些平台还要注册, 实际阿里云是有阿里云OpenSDK 可以支持的,本来想自己写了一个,后面发现有人已经实现了, 就用了一个开发者的DDNS服务, https://ddns.bkood.com/, 在这里非常感…

群晖设置腾讯云ddns显示认证失败的两种解决办法【实测第二种成功了】

群晖腾讯云ddns显示认证失败 背景:问题:前提条件解决办法一:群晖自带的ddns解析步骤1:获取 API 密钥信息步骤2:群晖(Synology)NAS 配置 DDNS 解决办法二:利用Docker安装DDNS动态域名…

群晖IPv6/ddns-go/域名解析设置内网穿透方案

前言 群晖的内网穿透有很多方案,外网IPv4(这个现在很难搞到了),中间服务器搭建Tunnel隧道,frp等方案(网速慢,流量限制,需另购服务器),第三方服务花生壳等(按量付费,速度问题)。 本篇介绍的是 …