连接器处理重复符号(二)具体不同地址的全局对象

这篇具有很好参考价值的文章主要介绍了连接器处理重复符号(二)具体不同地址的全局对象。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

问题

在下面这个例子中,可执行程序app链接一个静态库libsingleton.a和两个动态库libfirst.solibsecond.so

  • 静态库libsingleton.a是一个单例对象,在动态库libfirst.solibsecond.so中都被链接。
  • 可执行程序app链接静态库libsingleton.a,动态库libfirst.solibsecond.so

在动态库,可执行程序中都调用了单例对象singletonDoSomething方法,它将输出单例对象的地址。最终输出的结果是每个对象的地址都不相同。这显然不符合我们的预期。就好比原本有一个封装了日志功能的静态,被多个动态库链接使用,本意是都使用同一个日志全局对象输出日志,结果缺产生了多个日志对象,这显然是不符合业务需求的。
先看下这个例子:

例子

生成静态库libsingleton.a
class Singleton {
public:
    static Singleton* GetInstance();
    static void Release();
public:
	void DoSomething(void);
private:
    Singleton(){};
    ~Singleton(){};
private:
	static Singleton* _instance;

};
#include <iostream>
#include "singleton.h"
Singleton* Singleton::_instance = nullptr;

Singleton* Singleton::GetInstance(void) {
    if (nullptr == _instance) {
        _instance = new Singleton();
    }

    return _instance;
}

void Singleton::Release() {
    if (nullptr != _instance) {
        delete _instance;
        _instance = nullptr;
    }
    
}

void Singleton::DoSomething(void) {
    std::cout<<"singleton:"<<_instance<<std::endl;
}

单例类singleton,把它编译为一个静态库。

g++ -Wall -g -fPIC -c singleton.cpp -std=c++11
ar -rcs libsingleton.a singleton.o

生成动态库libfirst.so
#ifdef __cplusplus
extern "C"
{
    void firstshlibFunction(void);
}
#endif
#include <iostream>
#include "singleton.h"
#include "firstshlib.h"
#define FUNC_EXPORT __attribute__((visibility("default")))

#ifdef __cplusplus
extern "C" {
void FUNC_EXPORT firstshlibFunction(void) {
    std::cout<<__FUNCTION__<<std::endl;
    Singleton::GetInstance()->DoSomething();
}

void firshlibOtherFunction(void) {
    std::cout<<__FUNCTION__<<std::endl;
}
}
#endif //__cplusplus
控制动态的导出符号

导出符号控制脚本,传递给链接器:

{
    global:
        firstshlibFunction;
    local:
        *;
};

使libfirst.so只导出符号firstshlibFunction

g++ -Wall -g -fPIC -I…/staticLib -c firstshlib.cpp
g++ -shared firstshlib.o -L…/staticLib -lsingleton -Wl,–version-script=versionScript -Wl,-soname,libfirst.so.1 -o libfirst.so.1.0.0

通过nm libfirst.so | grep c++filt查看libfirst.so的导出符号,如下:

0000000000000aec t Singleton::DoSomething()
0000000000000a58 t Singleton::GetInstance()
0000000000000aa0 t Singleton::Release()
0000000000202068 b Singleton::_instance
0000000000000b9a t Singleton::Singleton()
0000000000000b9a t Singleton::Singleton()
0000000000000ba4 t Singleton::~Singleton()
0000000000000ba4 t Singleton::~Singleton()
0000000000000985 T firstshlibFunction

因为libfirst.so链接了静态库libsingleton.a,它会包含静态库中的所有符号,默认情况下这些静态库都会标示为导出符号,通过连接器脚本versionScript将这些静态库符号隐藏,只导出符号firstshlibFunction

生成动态库libsecond.so
#ifdef __cplusplus
extern "C"
{
    void secondshlibFunction(void);
}
#endif

#include <iostream>
#include "singleton.h"
#ifdef __cplusplus
extern "C"
{
void secondshlibFunction(void) {
    std::cout<<__FUNCTION__<<std::endl;
    Singleton::GetInstance()->DoSomething();
}
}
#endif

编译为动态库libsecond.so,它也依赖静态库libsingleton.a,只导出符号secondshlibFunction

g++ -Wall -g -I./staticLib -I./firstshlib -I./secondshlib -c main.cpp
g++ main.o -L./staticLib -lsingleton -L./firstshlib -lfirst -L./secondshlib -lsecond -Wl,-R./firstshlib -Wl,-R./secondshlib -o app

生成可执行文件app
#include <iostream>
#include "singleton.h"
#include "firstshlib.h"
#include "secondshlib.h"
int main(void) {
    firstshlibFunction();
    secondshlibFunction();

    Singleton::GetInstance()->DoSomething();
}

可执行程序app,它也依赖静态库libsingleton.a,并且链接libfirst.solibsecond.so

g++ -Wall -g -I./staticLib -I./firstshlib -I./secondshlib -c main.cpp
g++ main.o -L./staticLib -lsingleton -L./firstshlib -lfirst -L./secondshlib -lsecond -Wl,-R ./firstshlib -Wl,-R./secondshlib -o app

问题

执行app,输出如下,全局对象的地址各不同。

firstshlibFunction
singleton:0x24f9c20
secondshlibFunction
singleton:0x24f9c40
singleton:0x24f9c60

虽然在静态库中有全局的单例对象,但是**libfirst.so****libsecond.so****app**中各自有**singleton**符号,所以全局对象地址各不相同。
这是因为没有导出**singleton**符号,所以在最终生成可执行程序**app**时,静态库中的符号作为内部符号并没有参与链接。

解决方法:

解决这种问题的方法就是,在任意一个动态库中将静态库的符号导出即可,让这些符号参与可执行文件的链接。
最优雅的方法是将这种全局功能实现为一个动态库,而非静态库。文章来源地址https://www.toymoban.com/news/detail-431985.html

到了这里,关于连接器处理重复符号(二)具体不同地址的全局对象的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【腾讯云】腾讯云HiFlow场景连接器

    iFlow场景连接器是腾讯云推出的一个免费的应用连接自动化工具。提供助力办公流程自动化的场景连接工具,可以零代码的连接你的多个应用,鼠标轻点即可轻松设置自动化的工作流程数据流程,轻松实现日常办公任务的自动化操作。 通过场景连接器,你可以轻松快速实现如

    2024年02月16日
    浏览(46)
  • 关于服务连接器(Servlet)你了解多少?

    Servlet是JavaWeb最为核心的内容,它是Java提供的一门 动态 web资源开发技术。 使用Servlet就可以实现,根据不同的登录用户在页面上动态显示不同内容。 Servlet是JavaEE规范之一,其实就是一个接口,将来我们需要定义Servlet类实现Servlet接口,并由web服务器运行Servlet 介绍完Servlet是

    2024年01月18日
    浏览(40)
  • JavaWeb-Servlet服务连接器(终)

    上一篇文章JavaWeb-Servlet服务连接器(三)_Alphamilk的博客-CSDN博客 目录 1.ServletContext通信 会话技术Cookie与Session 1.Cookie 2.Session 概念:代表了整个web应用,用于与服务器实现通信 可以通过以下方法获取该对象 方法 描述 request.getServletContext() 返回与给定请求关联的Servlet上下文对象

    2024年02月13日
    浏览(41)
  • Flink系列之:Elasticsearch SQL 连接器

    Sink: Batch Sink: Streaming Append Upsert Mode Elasticsearch 连接器允许将数据写入到 Elasticsearch 引擎的索引中。本文档描述运行 SQL 查询时如何设置 Elasticsearch 连接器。 连接器可以工作在 upsert 模式,使用 DDL 中定义的主键与外部系统交换 UPDATE/DELETE 消息。 如果 DDL 中没有定义主键,那么

    2024年02月04日
    浏览(54)
  • JavaWeb-Servlet服务连接器(二)

    目录 Request(获取请求信息) 1.获取请求行内容 2.解决乱码问题  3.获取请求头部分 4.获取请求体  5.其他功能 工作流程: 1.通过请求的url的资源路径,tomcat会生成相应的Servlet实现对象。 2.tomcat服务器会创建request对象和response对象,request对象接收请求消息数据。 3.tomcat将req

    2024年02月13日
    浏览(45)
  • JavaWeb-Servlet服务连接器(一)

    目录  1.Servlet生命周期 2.Servlet的配置 3.Servlet的常用方法 4.Servlet体系结构 5.HTTP请求报文 6.HTTP响应报文 Servlet(Server Applet)是Java Servlet的简称。其主要的功能是交互式地浏览和修改数据,生成一些动态的Web内容。  Servlet的生命周期 可以简述为以下几个步骤: Servlet容器接收到

    2024年02月13日
    浏览(41)
  • Flink系列之:JDBC SQL 连接器

    Scan Source: Bounded Lookup Source: Sync Mode Sink: Batch Sink: Streaming Append Upsert Mode JDBC 连接器允许使用 JDBC 驱动向任意类型的关系型数据库读取或者写入数据。本文档描述了针对关系型数据库如何通过建立 JDBC 连接器来执行 SQL 查询。 如果在 DDL 中定义了主键,JDBC sink 将以 upsert 模式与外

    2024年02月02日
    浏览(43)
  • Semantic Kernel 入门系列:?Connector连接器

    当我们使用Native Function的时候,除了处理一些基本的逻辑操作之外,更多的还是需要进行外部数据源和服务的对接,要么是获取相关的数据,要么是保存输出结果。这一过程在Semantic Kernel中可以被归类为Connector。 Connector更像是一种设计模式,并不像Function和Memory 一样有强制和

    2023年04月15日
    浏览(42)
  • Unity里使用数字孪生网络连接器HslCommunication

    HslCommunication安装 去官网下载 胡工科技 https://github.com/dathlin/HslCommunication hslcommunication安装目录下找到库文件引入进unity里,本人Unity2021.2.12f1 低版本可能还要引入Newtonsoft.Json.dll,本版本不用 在Unity里测试http server服务 新建一个脚本挂到相机上测试 编写httpserver 服务内容    运行

    2024年02月11日
    浏览(50)
  • 服务器及周边高速连接器接口汇总(-)----概述

      一、服务器中的连接器接口概述    1. PCIe    2. miniPCIe    3. M.2/NGFF    4. SATA/SAS/U.2/U.3    5.miniSAS/miniSAS HD    6. slimlink/ oculink(Minilink SAS)    7. SFP系列     8.  OCP2/OCP3    9. CPCI   10. M8/M12    11.  USB/HMDI/DP/thunderbolt 二、各连接器接口的详细规格说明 一. 服务器中的连接器概

    2024年02月09日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包