草庐IT

c++ - 为什么在堆栈中我的函数局部变量之间有内存空间?

coder 2024-02-14 原文

我有一个在 Ubuntu x86 上用 gcc 编译的 C 程序。这是我从 main

调用的函数
void addme()
{
  long a = 5;
  char c = '3';
  long array[3];
  array[0] = 2;
  array[1] = 4;
  array[2] = 8;
}

如果我在最后一行中断,然后调试/检查这就是我得到的

(gdb) print &a
$5 = (long *) 0xbffff04c
(gdb) print &c
$6 = 0xbffff04b "3\005"
(gdb) print &array
$7 = (long (*)[3]) 0xbffff03c
(gdb) x 0xbffff03c
0xbffff03c:     0x00000002
(gdb) x 0xbffff040
0xbffff040:     0x00000004
(gdb) x 0xbffff044
0xbffff044:     0x00000008
(gdb) x 0xbffff04c
0xbffff04c:     0x00000005

为什么 0xbffff048、0xbffff049、0xbffff04a 和 0xbffff04b 保留给 char c 而只需要 0xbffff04b 来存储一个 char?

还有这个符号 "3\005" 是什么意思?

另一方面,如果我的方法如下,则没有填充额外三个字节的存储空间

void addme()
{
  long a = 5;
  char c = '3';
  char line[9];
  char d = '4';
}

这就是这些变量的内存分配方式(跳过地址的前导部分)

a - f04c 
c - f04b 
d - f04a 
line - f041, f042, f043, f044, f045, f046, f047, f048, f049

也不确定为什么 d 在内存预留中被提升到 line 之上。我假设因为它没有被初始化,所以它进入了堆栈中与初始化变量不同的区域?

最佳答案

这叫做 alignment .对象与特定整数的倍数对齐(在 long 的情况下通常为 4 或 8)以便快速访问。 通常,您不必太担心 C++ 中的位置,因为语言规范通常使编译器能够选择最有效(根据您的优化方向)的方式来存储对象,通常情况就是这样.

Every object type has the property called alignment requirement, which is an integer value (of type std::size_t, always a power of 2) representing the number of bytes between successive addresses at which objects of this type can be allocated. The alignment requirement of a type can be queried with alignof or std::alignment_of. The pointer alignment function std::align can be used to obtain a suitably-aligned pointer within some buffer, and std::aligned_storage can be used to obtain suitably-aligned storage.

Each object type imposes its alignment requirement on every object of that type; stricter alignment (with larger alignment requirement) can be requested using alignas.

In order to satisfy alignment requirements of all non-static members of a class, padding may be inserted after some of its members.

(cppreference)


关于你的第二个问题,@prl给出答案:

Because c is a char, &c is a char *, so gdb prints it as a string. The first character of the string is '3', the value of c. The next character is 5, the low byte of a, which gdb prints in octal escape notation. Escape sequences in C on Wikipedia – prl 1024 min ago


为什么在 char 之后声明 char 时 pad 消失了?因为在这种情况下,char 的对齐方式显示为 1,这意味着不需要填充。另一方面,long 似乎是 4,因此必须有一个 4 字节的空间,其中放置 char

I assume because it wasn't initialized, it goes to a different region in stack than initialized variables?

不是真的。一个变量是否被初始化(通常)并不影响它的位置,只是它有一个不确定的值。另一方面,编译器可以自由地将对象按照自己喜欢的方式放置在内存中。在实践中,编译器“喜欢”在内存和时间上带来效率的实现。

关于c++ - 为什么在堆栈中我的函数局部变量之间有内存空间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54453306/

有关c++ - 为什么在堆栈中我的函数局部变量之间有内存空间?的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  3. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  4. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  5. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  6. ruby - 为什么 4.1%2 使用 Ruby 返回 0.0999999999999996?但是 4.2%2==0.2 - 2

    为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返

  7. ruby-on-rails - Rails 应用程序之间的通信 - 2

    我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此

  8. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  9. ruby-on-rails - 如何使用 instance_variable_set 正确设置实例变量? - 2

    我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击

  10. ruby - 通过 ruby​​ 进程共享变量 - 2

    我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是

随机推荐