- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我试图理解 .bss 内存分配和释放背后的逻辑
我尝试理解的案例很少。
我的结论是,如果我在代码的全局范围内声明任何变量,它会以 8 字节为单位递增,因为我的链接描述文件具有 8 字节的对齐
但是当我在同一范围内定义变量时,它正在从 .bss 中释放内存
但是我不明白释放背后的逻辑计算到底是什么?
案例一:
#include <stdio.h>
int a;
int b;
int main(void){
return 0;
}
此代码片段为不同的 segmentation 生成以下尺寸
text data bss dec hex filename
1418 544 16 1978 7ba a.out
现在如果我像这样初始化一个 int 变量
案例二:
#include <stdio.h>
int a = 1;
int b;
int main(void){
return 0;
}
这给了我以下尺寸表
text data bss dec hex filename
1418 548 12 1978 7ba a.out
现在如果我像这样在 int 变量之前初始化一个字符
案例三:
#include <stdio.h>
char a = 1;
int b;
int main(void){
return 0;
}
正在显示
text data bss dec hex filename
1418 545 12 1978 7ba a.out
这是专门针对案例 3 的 nm -n 输出
0000000000004000 D __data_start
0000000000004000 W data_start
0000000000004008 D __dso_handle
0000000000004010 D a
0000000000004011 B __bss_start
0000000000004011 D _edata
0000000000004014 b completed.8060
0000000000004018 D __TMC_END__
0000000000004018 B b
0000000000004020 B _end
现在如果我像这样初始化一个 int 变量
案例 4:
#include <stdio.h>
int a = 1;
char b;
int main(void){
return 0;
}
正在显示
text data bss dec hex filename
1418 548 4 1978 7ba a.out
现在如果我像这样初始化一个 int 变量
案例 5:
#include <stdio.h>
char a = 1;
char b;
int main(void){
return 0;
}
正在显示
text data bss dec hex filename
1418 545 7 1978 7ba a.out
谁能帮我理解一下?
最佳答案
给定类型的符号具有链接器必须遵守的自然对齐方式(例如,int
必须为 4 字节对齐)。在给定的部分(例如 .bss
)中,链接器有一些余地来重新排序符号,以便给定符号的对齐不会导致过多的填充。如果我们有:
char a;
int b;
如果不重新排序,加载图将如下所示:
0000 a
0004 b
并且,部分长度为 8。
重新排序:
0000 b
0000 a
并且,部分长度为 5
请注意,部分的大小对齐到某个倍数(通常为 8 字节)。因此,例如,如果一个部分只有 1 个字节的数据,则该部分大小将报告为 8。
但是,也有异常(exception)。
更清楚地看到这一点的方法之一是简化数据:
我们可以省略任何库或启动代码以减少可执行文件的大小。
我们可以使用相对于 第一个 数据部分开始的地址(例如 .data
的开始)
将所有案例的结果合并到一个表中
我已经创建了一个 [perl] 脚本来执行此操作。它有您的原始测试用例和一些额外的测试用例。
特别值得注意的是案例 6 ...
下面是脚本的输出。决赛 table [和讨论] 在下面的 FINAL 部分。
案例 1:
来源:
int a;
int b;
int _start(void) { return 0; }
命令:nm -n xfile
0000 B b
0000 B __bss_start
0000 B _edata
0004 B a
0008 B _end
命令:大小 xfile
text data bss dec hex filename
50 0 8 58 3a xfile
案例 2:
来源:
int a = 1;
int b;
int _start(void) { return 0; }
命令:nm -n xfile
0000 D a
0004 B b
0004 B __bss_start
0004 D _edata
0008 B _end
命令:大小 xfile
text data bss dec hex filename
50 4 4 58 3a xfile
案例三:
来源:
char a = 1;
int b;
int _start(void) { return 0; }
命令:nm -n xfile
0000 D a
0001 B __bss_start
0001 D _edata
0004 B b
0008 B _end
命令:大小 xfile
text data bss dec hex filename
50 1 4 55 37 xfile
案例 4:
来源:
int a = 1;
char b;
int _start(void) { return 0; }
命令:nm -n xfile
0000 D a
0004 B b
0004 B __bss_start
0004 D _edata
0008 B _end
命令:大小 xfile
text data bss dec hex filename
50 4 4 58 3a xfile
案例 5:
来源:
char a = 1;
char b;
int _start(void) { return 0; }
命令:nm -n xfile
0000 D a
0001 B b
0001 B __bss_start
0001 D _edata
0008 B _end
命令:大小 xfile
text data bss dec hex filename
50 1 7 58 3a xfile
案例 6:
来源:
char a;
int b;
char c = 1;
int d = 1;
int _start(void) { return 0; }
命令:nm -n xfile
0000 D d
0004 D c
0005 B __bss_start
0005 D _edata
0008 B b
000C B a
0010 B _end
命令:大小 xfile
text data bss dec hex filename
50 5 8 63 3f xfile
最终:
CASE DATA BSS DEFS
1 0 8 int a; int b;
00/B/b 00/B/__bss_start 00/B/_edata 04/B/a 08/B/_end
2 4 4 int a = 1; int b;
00/D/a 04/B/b 04/B/__bss_start 04/D/_edata 08/B/_end
3 1 4 char a = 1; int b;
00/D/a 01/B/__bss_start 01/D/_edata 04/B/b 08/B/_end
4 4 4 int a = 1; char b;
00/D/a 04/B/b 04/B/__bss_start 04/D/_edata 08/B/_end
5 1 7 char a = 1; char b;
00/D/a 01/B/b 01/B/__bss_start 01/D/_edata 08/B/_end
6 5 8 char a; int b; char c = 1; int d = 1;
00/D/d 04/D/c 05/B/__bss_start 05/D/_edata 08/B/b 0C/B/a 10/B/_end
请注意,在情况 6 中,.data
长度为 5。并且,.bss
的起始地址也是 [also] 5。但是,最低的 .bss
地址实际使用 是 8(对于 b
)
这是脚本源:
#!/usr/bin/perl
# bssgen -- generate .bss data
#
# options:
# "-c" -- use .o instead of executable
# "-O" -- optimzation level (DEFAULT: 2)
# "-v" -- output to stdout (DEFAULT: off)
master(@ARGV);
exit(0);
sub master
{
my(@argv) = @_;
$opt_c = 0;
$opt_O = 2;
$pubfile = "bssgen.txt";
printf("output to %s\n",$pubfile);
$xfpub = xfopen(">$pubfile","master");
optget(\@argv,
["c",1],
["n",1],
["O",1]);
my($xfsrc) = "bssgen::DATA";
$xfsrc = \*$xfsrc;
while ($bf = <$xfsrc>) {
chomp($bf);
if ($bf =~ /^\s*$/) {
dotest();
}
else {
push(@defs,$bf);
}
}
dotest()
if (@defs > 0);
final();
$xfpub = xfclose($xfpub);
}
sub final
{
prtsct("FINAL:");
prtsep();
@prtcol_tabs = (0,8,16,24);
prtcol("%s","CASE");
prtcol("%s","DATA");
prtcol("%s","BSS");
prtcol("%s","DEFS");
prtcol();
$caseno = 0;
foreach $tst (@tstlist) {
++$caseno;
prtcol("%d",$caseno);
prtcol("%d",$tst->{tst_data});
prtcol("%d",$tst->{tst_bss});
prtcol("%s",$tst->{tst_defs});
prtcol();
prtcol("%s");
prtcol("%s");
prtcol("%s");
my($buf);
my($nmlhs) = $tst->{tst_nm};
my($base);
foreach $nm (@$nmlhs) {
$buf .= " "
if (defined($buf));
$buf .= sprintf("%2.2X/%s/%s",
$nm->{addr},$nm->{typ},$nm->{sym});
}
prtcol("%s",$buf);
prtcol();
}
prtsep();
}
sub dotest
{
prtsct("Case %d:",++$caseno);
my($root) = "xfile";
my($sfile) = $root . ".c";
my($ofile) = $root . ".o";
my($xfile) = $root;
my($run) = $root;
local($xfdst) = xfopen(">$sfile","dotest/sfile");
prtpub("Source:\n");
prtsep();
foreach $bf (@defs) {
prtcode("%s\n",$bf);
}
prtcode("int %s(void) { return 0; }\n",$opt_c ? "main" : "_start");
prtsep();
$xfdst = xfclose($xfdst);
my(@cflags);
push(@cflags,"-O")
if ($opt_O);
push(@cflags,"-c");
doexec("cc",@cflags,$sfile);
unless ($opt_c) {
doexec("ld","-o",$xfile,$ofile);
$run = $xfile;
}
else {
$run = $ofile;
}
my(@nm);
push(@nm,"-n");
@nmrhs = grab(0,"nm",@nm,$run);
my($base);
my(@nmlhs);
prtsep();
foreach $nm (@nmrhs) {
chomp($nm);
my($addr,$typ,$sym) = split(" ",$nm);
next if ($typ eq "T");
$addr = hex("0x$addr");
$base //= $addr;
$nm = {};
$nm->{addr} = $addr - $base;
$nm->{typ} = $typ;
$nm->{sym} = $sym;
prtpub("%4.4X %s %s\n",$nm->{addr},$nm->{typ},$nm->{sym});
push(@nmlhs,$nm);
}
prtsep();
my(@siz) = grab(1,"size",$run);
my($txt,$data,$bss) = split(" ",$siz[1]);
my($tst) = {};
$tst->{tst_defs} = join(" ",@defs);
$tst->{tst_data} = $data + 0;
$tst->{tst_bss} = $bss + 0;;
$tst->{tst_nm} = \@nmlhs;
push(@tstlist,$tst);
unless ($opt_k) {
unlink($sfile);
unlink($ofile);
unlink($xfile);
}
undef(@defs);
}
sub xfopen
{
my($file,$who) = @_;
my($xf);
open($xf,$file) or
die("xfopen: unable to open '$file' -- $!\n");
$xf;
}
sub xfclose
{
my($xf) = @_;
close($xf);
undef($xf);
$xf;
}
sub grab
{
my($vflg,@argv) = @_;
my($cmd,@cmd);
$cmd = $argv[0];
prtpub("\n");
$cmd = join(" ",@argv);
prtpub("Command: `%s`\n",$cmd);
@cmd = (`$cmd`);
prtsep()
if ($vflg);
foreach $cmd (@cmd) {
chomp($cmd);
prtpub("%s\n",$cmd)
if ($vflg);
}
prtsep()
if ($vflg);
@cmd;
}
sub doexec
{
$_ = join(" ",@_);
system($_);
$_ = $? >> 8;
exit($_) if ($_);
}
sub prtsct
{
my($fmt,$arg) = @_;
prtpub("\n");
prtpub("%s\n","-" x 8);
$fmt = "**" . $fmt . "**\n";
prtpub($fmt,$arg);
prtpub("\n");
}
sub prtsep
{
prtpub("```\n");
}
sub prtcol
{
my($fmt,$val) = @_;
my($tabto);
{
unless (defined($fmt)) {
prtpub("%s\n",$prtcol_buf);
undef($prtcol_buf);
undef($prtcol_idx);
last;
}
$tabto = $prtcol_tabs[$prtcol_idx++];
while (length($prtcol_buf) < $tabto) {
$prtcol_buf .= " ";
}
$fmt = sprintf($fmt,$val);
$prtcol_buf .= $fmt;
}
}
sub prtpub
{
my($fmt);
$fmt = shift(@_);
printf($xfpub $fmt,@_);
printf($fmt,@_)
if ($opt_v);
}
sub prtcode
{
my($fmt);
$fmt = shift(@_);
printf($xfdst $fmt,@_);
prtpub($fmt,@_);
}
sub optget
{
my($argv,@opts) = @_;
my($arg,$opt);
my($sym,$val);
@opts = sort({ $b->[0] cmp $a->[0]} @opts);
while (@$argv > 0) {
$arg = $argv->[0];
last unless ($arg =~ s/^-//);
shift(@$argv);
foreach $opt (@opts) {
my($sym,$dft) = @$opt;
if ($arg =~ /^$sym(.*)$/) {
$val = $1;
{
last if ($val =~ s/^=//);
last if ($val ne "");
$val = $dft;
}
${"opt_" . $sym} = $val;
last;
}
}
}
foreach $opt (@opts) {
my($sym,$dft) = @$opt;
$sym = "opt_" . $sym;
###printf("optget: DEBUG_CAE %s %s\n",$sym,$$sym);
}
}
package bssgen;
__DATA__
int a;
int b;
int a = 1;
int b;
char a = 1;
int b;
int a = 1;
char b;
char a = 1;
char b;
char a;
int b;
char c = 1;
int d = 1;
关于c - .bss 段如何为 C 程序分配和释放内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72805131/
我是 C 语言新手,我编写了这个 C 程序,让用户输入一年中的某一天,作为返回,程序将输出月份以及该月的哪一天。该程序运行良好,但我现在想简化该程序。我知道我需要一个循环,但我不知道如何去做。这是程序
我一直在努力找出我的代码有什么问题。这个想法是创建一个小的画图程序,并有红色、绿色、蓝色和清除按钮。我有我能想到的一切让它工作,但无法弄清楚代码有什么问题。程序打开,然后立即关闭。 import ja
我想安装screen,但是接下来我应该做什么? $ brew search screen imgur-screenshot screen
我有一个在服务器端工作的 UDP 套接字应用程序。为了测试服务器端,我编写了一个简单的 python 客户端程序,它发送消息“hello world how are you”。服务器随后应接收消息,将
我有一个 shell 脚本,它运行一个 Python 程序来预处理一些数据,然后运行一个 R 程序来执行一些长时间运行的任务。我正在学习使用 Docker 并且我一直在运行 FROM r-base:l
在 Linux 中。我有一个 c 程序,它读取一个 2048 字节的文本文件作为输入。我想从 Python 脚本启动 c 程序。我希望 Python 脚本将文本字符串作为参数传递给 c 程序,而不是将
对于一个类,我被要求编写一个 VHDL 程序,该程序接受两个整数输入 A 和 B,并用 A+B 替换 A,用 A-B 替换 B。我编写了以下程序和测试平台。它完成了实现和行为语法检查,但它不会模拟。尽
module Algorithm where import System.Random import Data.Maybe import Data.List type Atom = String ty
我想找到两个以上数字的最小公倍数 求给定N个数的最小公倍数的C++程序 最佳答案 int lcm(int a, int b) { return (a/gcd(a,b))*b; } 对于gcd,请查看
这个程序有错误。谁能解决这个问题? Error is :TempRecord already defines a member called 'this' with the same paramete
当我运行下面的程序时,我在 str1 和 str2 中得到了垃圾值。所以 #include #include #include using namespace std; int main() {
这是我的作业: 一对刚出生的兔子(一公一母)被放在田里。兔子在一个月大时可以交配,因此在第二个月的月底,每对兔子都会生出两对新兔子,然后死去。 注:在第0个月,有0对兔子。第 1 个月,有 1 对兔子
我编写了一个程序,通过对字母使用 switch 命令将十进制字符串转换为十六进制,但是如果我使用 char,该程序无法正常工作!没有 switch 我无法处理 9 以上的数字。我希望你能理解我,因为我
我是 C++ 新手(虽然我有一些 C 语言经验)和 MySQL,我正在尝试制作一个从 MySQL 读取数据库的程序,我一直在关注这个 tutorial但当我尝试“构建”解决方案时出现错误。 (我正在使
仍然是一个初学者,只是尝试使用 swift 中的一些基本函数。 有人能告诉我这段代码有什么问题吗? import UIKit var guessInt: Int var randomNum = arc
我正在用 C++11 编写一个函数,它采用 constant1 + constant2 形式的表达式并将它们折叠起来。 constant1 和 constant2 存储在 std::string 中,
我用 C++ 编写了这段代码,使用运算符重载对 2 个矩阵进行加法和乘法运算。当我执行代码时,它会在第 57 行和第 59 行产生错误,非法结构操作(两行都出现相同的错误)。请解释我的错误。提前致谢:
我是 C++ 的初学者,我想编写一个简单的程序来交换字符串中的两个字符。 例如;我们输入这个字符串:“EXAMPLE”,我们给它交换这两个字符:“E”和“A”,输出应该类似于“AXEMPLA”。 我在
我需要以下代码的帮助: 声明 3 个 double 类型变量,每个代表三角形的三个边中的一个。 提示用户为第一面输入一个值,然后 将用户的输入设置为您创建的代表三角形第一条边的变量。 将最后 2 个步
我是新来的,如果问题不好请见谅 任务:将给定矩阵旋转180度 输入: 1 4 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 输出: 16 15 14 13 12 11
我是一名优秀的程序员,十分优秀!