热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

为什么GCC在初始化为0时不分配静态变量

如何解决《为什么GCC在初始化为0时不分配静态变量》经验,为你挑选了1个好方法。

我将静态变量初始化为0,但是当我看到汇编代码时,我发现只有内存分配给该变量。该值未分配
。当我将静态变量初始化为其他数字时,我可以发现内存已分配了一个值。
我猜想GCC是否认为应该在使用内存之前由OS将内存初始化为0。

我使用的GCC选项是“ gcc -m32 -fno-stack-protector -c -o”

当我将静态变量初始化为0时,C代码和汇编代码为:

static int temp_frOnt=0;
.local  temp_front.1909
.comm   temp_front.1909,4,4

当我将其初始化为其他数字时,代码为:

.local  temp_front.1909
.comm   temp_front.1909,4,4
    .align 4
    .type   temp_front.1909, @object
    .size   temp_front.1909, 4
temp_front.1909:
    .long   1

Michael Karc.. 9

TL:DR:GCC知道BSS保证在目标平台上被零初始化,因此它将零初始化的静态数据放在那里。

大图

大多数现代操作系统的程序加载器对于程序的每个部分(如数据部分)都有两种不同的大小。它得到的第一个大小是可执行文件(例如Windows上的PE / COFF.EXE文件或Linux 上的ELF可执行文件)中存储的数据大小,而第二个大小是程序运行时内存中数据部分的大小。 。

如果正在运行的程序的数据大小大于可执行文件中存储的数据量,则数据部分的其余部分将填充包含零的字节。在您的程序中,该.comm行告诉链接器保留4个字节而不初始化它们,以便OS在启动时将它们零初始化。

gcc做什么?

gcc(或任何其他C编译器)在本.bss节中分配零静态存储持续时间的变量。该部分中分配的所有内容都将在程序启动时初始化为零。对于分配,它使用comm伪指令,并且仅指定大小(4个字节)。

您可以使用size命令查看主要部分类型(代码,数据,bss)的大小。如果使用1初始化变量,则它将包含在一个data节中,并在其中占据4个字节。如果将其初始化为零(或根本不初始化),则将其分配给.bss部分。

ld是做什么的?

ld将所有目标文件的所有数据类型部分(甚至是静态库中的文件)合并到一个数据部分中,然后合并所有.bss-type部分。可执行输出包含操作系统程序加载器的简化视图。对于ELF文件,这是“ 程序头 ”。您可以使用objdump -p任意格式或readelfELF文件来查看它。

程序头包含不同类型的条目。其中有几个条目,其类型PT_LOAD描述了操作系统要加载的“段”。这些PT_LOAD条目之一用于数据区(.data链接该节的位置)。它包含一个条目p_filesz,该条目指定在ELF文件中提供多少个用于初始化变量的字节,以及一个条目,p_memsz告诉加载程序应该在地址空间中保留多少空间。关于哪些部分合并到链接器之间不同的PT_LOAD条目的细节取决于命令行选项,但是通常您会找到一个PT_LOAD条目,该条目描述了一个既可读又可写但不可执行的区域,其p_filesz值是小于p_memsz项(如果只有一个.bss,则没有.data节,则可能为零)。p_filesz是所有读写数据部分的大小,而p_memsz较大则还为零初始化变量提供了空间。

数量p_memsz超过链接到可执行文件p_filesz的所有.bss部分的总和。(由于与页面或磁盘块的对齐,这些值可能会有些偏差)

有关程序头条目的说明,请参见System V ABI规范的第5章,尤其是第5-2和5-3页。

操作系统做什么?

Linux内核(或另一个兼容ELF的内核)遍历程序头文件中的所有条目。对于每个包含类型的条目,PT_LOAD它分配虚拟地址空间。它将地址空间的开头与可执行文件中的相应区域相关联,如果该空间可写,则启用写时复制。

如果p_memsz超过p_filesz,内核将剩余的地址空间安排为完全清零。因此,.bss由gcc 在本节中分配的变量最终出现在ELF文件中的PT_LOAD读写条目的“尾部”中,内核提供了零。

任何没有备份数据的整页都可以从写时复制开始映射到共享的零物理页。



1> Michael Karc..:

TL:DR:GCC知道BSS保证在目标平台上被零初始化,因此它将零初始化的静态数据放在那里。

大图

大多数现代操作系统的程序加载器对于程序的每个部分(如数据部分)都有两种不同的大小。它得到的第一个大小是可执行文件(例如Windows上的PE / COFF.EXE文件或Linux 上的ELF可执行文件)中存储的数据大小,而第二个大小是程序运行时内存中数据部分的大小。 。

如果正在运行的程序的数据大小大于可执行文件中存储的数据量,则数据部分的其余部分将填充包含零的字节。在您的程序中,该.comm行告诉链接器保留4个字节而不初始化它们,以便OS在启动时将它们零初始化。

gcc做什么?

gcc(或任何其他C编译器)在本.bss节中分配零静态存储持续时间的变量。该部分中分配的所有内容都将在程序启动时初始化为零。对于分配,它使用comm伪指令,并且仅指定大小(4个字节)。

您可以使用size命令查看主要部分类型(代码,数据,bss)的大小。如果使用1初始化变量,则它将包含在一个data节中,并在其中占据4个字节。如果将其初始化为零(或根本不初始化),则将其分配给.bss部分。

ld是做什么的?

ld将所有目标文件的所有数据类型部分(甚至是静态库中的文件)合并到一个数据部分中,然后合并所有.bss-type部分。可执行输出包含操作系统程序加载器的简化视图。对于ELF文件,这是“ 程序头 ”。您可以使用objdump -p任意格式或readelfELF文件来查看它。

程序头包含不同类型的条目。其中有几个条目,其类型PT_LOAD描述了操作系统要加载的“段”。这些PT_LOAD条目之一用于数据区(.data链接该节的位置)。它包含一个条目p_filesz,该条目指定在ELF文件中提供多少个用于初始化变量的字节,以及一个条目,p_memsz告诉加载程序应该在地址空间中保留多少空间。关于哪些部分合并到链接器之间不同的PT_LOAD条目的细节取决于命令行选项,但是通常您会找到一个PT_LOAD条目,该条目描述了一个既可读又可写但不可执行的区域,其p_filesz值是小于p_memsz项(如果只有一个.bss,则没有.data节,则可能为零)。p_filesz是所有读写数据部分的大小,而p_memsz较大则还为零初始化变量提供了空间。

数量p_memsz超过链接到可执行文件p_filesz的所有.bss部分的总和。(由于与页面或磁盘块的对齐,这些值可能会有些偏差)

有关程序头条目的说明,请参见System V ABI规范的第5章,尤其是第5-2和5-3页。

操作系统做什么?

Linux内核(或另一个兼容ELF的内核)遍历程序头文件中的所有条目。对于每个包含类型的条目,PT_LOAD它分配虚拟地址空间。它将地址空间的开头与可执行文件中的相应区域相关联,如果该空间可写,则启用写时复制。

如果p_memsz超过p_filesz,内核将剩余的地址空间安排为完全清零。因此,.bss由gcc 在本节中分配的变量最终出现在ELF文件中的PT_LOAD读写条目的“尾部”中,内核提供了零。

任何没有备份数据的整页都可以从写时复制开始映射到共享的零物理页。


推荐阅读
  • Linux系统快捷键大全及使用技巧
    本文详细介绍了Linux系统中的各种快捷键,包括命令行和VIM编辑器中的常用快捷键,帮助用户提高操作效率。同时,文章还提供了关于字体配置、软件安装等方面的实用信息。 ... [详细]
  • 本文详细介绍了Sleep函数的基本概念、使用方法及其背后的实现原理。适合对Sleep函数的使用和实现感兴趣的开发者阅读。通过本文,您将了解如何在不同操作系统中使用Sleep函数,以及其在多线程编程中的重要性。 ... [详细]
  • Vulnhub DC3 实战记录与分析
    本文记录了在 Vulnhub DC3 靶机上的渗透测试过程,包括漏洞利用、内核提权等关键步骤,并总结了实战经验和教训。 ... [详细]
  • 环境变量是用于描述系统运行环境的一系列变量,如PATH指定了命令的搜索路径,SHELL指定了默认的Shell。本文介绍了如何加载和管理这些环境变量,以及普通变量与环境变量的区别。 ... [详细]
  • top 命令是一个强大的工具,可以实时动态地监控系统的整体运行状况。它整合了多种信息,提供了一个全面的系统性能和运行信息视图。通过 top 命令的交互界面,用户可以使用热键进行各种管理操作。 ... [详细]
  • Linux环境下MySQL的安装与配置
    本文详细介绍了在Linux系统上安装和配置MySQL的步骤,包括安装前的准备工作、下载和解压安装包、初始化数据库、配置文件编辑、启动服务以及设置开机自启动等。 ... [详细]
  • 本文介绍了如何在Linux系统中将命令添加到PATH环境变量中,以便在任何位置都能直接运行这些命令。PATH是一个包含多个目录路径的字符串变量,当输入不带路径的命令时,系统会在这些路径中查找并执行相应的命令。 ... [详细]
  • 构建个人多节点Linux环境(CodeSheep)
    本文介绍如何通过虚拟机搭建一个多节点的Linux环境,这对于学习、实验和项目部署都具有重要意义。文章详细讲解了网络IP设置、节点间通信等关键步骤。 ... [详细]
  • 尽管Medium是一个优秀的发布平台,但在其之外拥有自己的博客仍然非常重要。这不仅提供了另一个与读者互动的渠道,还能确保您的内容安全。本文将介绍如何使用Bash脚本将Medium文章迁移到个人博客。 ... [详细]
  • 本文总结了近年来在实际项目中使用消息中间件的经验和常见问题,旨在为Java初学者和中级开发者提供实用的参考。文章详细介绍了消息中间件在分布式系统中的作用,以及如何通过消息中间件实现高可用性和可扩展性。 ... [详细]
  • CentOS7通过RealVNC实现多人使用服务器桌面
    背景:公司研发团队通过VNC登录到CentOS服务器的桌面实现软件开发工作为防止数据外泄,需要在RealVNC设置禁止传输文件、访问粘贴板等策略过程&# ... [详细]
  • Ubuntu 14.04 系统安装后网卡名称修改方法
    本文介绍了在安装 Ubuntu 14.04 Server 版本后,如何将默认的网卡名称从非 eth 格式修改为传统的 eth 格式,并提供了详细的步骤和示例。 ... [详细]
  • 1.前言PAP和CHAP协议是目前的在PPP(MODEM或ADSL拨号)中普遍使用的认证协议,CHAP在RFC1994中定义,是一种挑战响应式协议&#x ... [详细]
  • 本文介绍了如何在Linux系统中获取库源码,并在从源代码编译软件时收集所需的依赖项列表。 ... [详细]
  • 对象存储与块存储、文件存储等对比
    看到一篇文档,讲对象存储,好奇,搜索文章,摘抄,学习记录!背景:传统存储在面对海量非结构化数据时,在存储、分享与容灾上面临很大的挑战,主要表现在以下几个方面:传统存储并非为非结 ... [详细]
author-avatar
杰ZGJ8513
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有