当前位置: 首页 > news >正文

[c++] 意识需要转变的一个例子,全局变量的构造函数先于main执行

最近还遇到一个例子是关于:从C转C++开发需要注意的一个意识问题。本人遇到的这个问题是,带着C的意识来看C++的代码,然后根据代码看,有一个全局变量的值在main函数进入之后才会更改,所以百思不得其解,这个变量怎么在main函数之前发生了改变?

这里的一个区别是,C++里全局变量的构造函数是先于main函数执行。当然在C的环境下也可以注册先于main函数执行的代码,这个有名的例子就是qemu/vpp的实现,里面有很多全局对象,最终会标记一个编译属性:
attribute((constructor));根据gcc文档里这个属性的作用:
The constructor attribute causes the function to be called automatically before execution enters main (). Similarly, the destructor attribute causes the function to be called automatically after main () completes or exit () is called. Functions with these attributes are useful for initializing data that is used implicitly
during the execution of the program.
那究竟是怎么实现的呢?这个可用通过查看一个qemu的调用栈,来看其中的流程:

(gdb) bt
#0 0x0000555555c5f6b0 in qemu_thread_create ()
#1 0x0000555555c67f69 in ?? ()
#2 0x0000555555c9a88d in __libc_csu_init ()
#3 0x00007ffff4874d18 in __libc_start_main () from /lib64/libc.so.6
#4 0x00005555558a859e in _start ()

binfmt_elf.c
/* Get the exec-header */
loc->elf_ex = *((struct elfhdr *)bprm->buf);

[root@vmtca-2003 ~]# readelf -e abc.elf
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2’s complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Version: 0x1
Entry point address: 0x3afe0

nm abc.elf | grep 3afe0

000000003afe0 T _start

这样就能捋顺了,是Linux内核的系统调用execve系列在加载二进制文件的时候,根据二进制接口读取了文件的exe头部,这个头部里含有程序入口点。这个入口点是_start函数。接下来_start会做main函数之前的一些初始化的工作,包含全局变量的构造函数的调用。
这就可以根据glibc里的代码查看具体是怎么实现的这个方式。
在这里插入图片描述

http://www.lryc.cn/news/259950.html

相关文章:

  • VSCode 配置自动生成头文件
  • 【大数据】Hudi 核心知识点详解(一)
  • windows上抓包出现大包未分片以及关闭tso方法
  • Leetcode 2454. 下一个更大元素 IV
  • 浏览器全屏按键同f11效果
  • CentOS 7.9 安装 k8s(详细教程)
  • 区块链的可拓展性研究【05】闪电网络
  • 如何部署Portainer容器管理工具+cpolar内网穿透实现公网访问管理界面
  • Linux——Samba文件共享服务配置
  • 自动驾驶右向辅助功能规范
  • ASF-YOLO开源 | SSFF融合+TPE编码+CPAM注意力,精度提升!
  • Mac 如何删除文件及文件夹?可以尝试使用终端进行删除
  • 最新Redis7持久化(权威出版)
  • Redis权限管理体系(一):客户端名及用户名
  • 【数据库设计和SQL基础语法】--查询数据--排序
  • 【sqli靶场】第六关和第七关通关思路
  • c语言快速排序(霍尔法、挖坑法、双指针法)图文详解
  • 【mysql】锁的类型有哪些呢?
  • uniapp 显示文件流图片
  • 多线程------ThreadLocal详解
  • 【C++】POCO学习总结(十六):随机数、密码、时间戳、日期和时间(格式化与解析)、时区、本地时间
  • 打补丁,生成.diff文件
  • 《LeetCode力扣练习》代码随想录——字符串(KMP算法学习补充——针对next数组构建的回退步骤进行解释)
  • 【CANoe】CAPL中on signal和on signal_update的区别
  • ArrayList集合的两个实例应用,有趣的洗牌算法与杨辉三角
  • Qt 剪贴板操作
  • python 学习笔记20 批量修改页眉页脚
  • IIS + Axios 跨域设置
  • 详细说说vuex
  • Qt之Ui样式表不影响子类的配置