jjzjj

c++ - 结构大小和内存布局取决于#pragma pack

coder 2024-02-22 原文

考虑以下在 VC++ 2010 中编译的程序:

#pragma pack(push, 1)    // 1, 2, 4, 8
struct str_test
{
    unsigned int n;
    unsigned short s;
    unsigned char b[4];
};
#pragma pack(pop)

int main()
{
    str_test str;
    str.n = 0x01020304;
    str.s = 0xa1a2;
    str.b[0] = 0xf0;
    str.b[1] = 0xf1;
    str.b[2] = 0xf2;
    str.b[3] = 0xf3;

    unsigned char* p = (unsigned char*)&str;
    std::cout << sizeof(str_test) << std::endl;
    return 0;
}

我在 return 0; 行上设置断点并在调试器中查看内存窗口,从地址 p 开始。我得到以下结果(sizeof 和内存布局,具体取决于 pack):

// 1 - 10    (pack, sizeof)
// 04 03 02 01 a2 a1 f0 f1 f2 f3

// 2 - 10
// 04 03 02 01 a2 a1 f0 f1 f2 f3

// 4 - 12
// 04 03 02 01 a2 a1 f0 f1 f2 f3

// 8 - 12
// 04 03 02 01 a2 a1 f0 f1 f2 f3

两个问题:

  1. 为什么 pack 8 的 sizeof(str_test) 是 12?

  2. 为什么内存布局相同且不依赖于 pack 值?

最佳答案

Why sizeof(str_test) is 12 for pack 8?

来自MSDN docs :

The alignment of a member will be on a boundary that is either a multiple of n or a multiple of the size of the member, whichever is smaller.

在您的情况下,最大的成员是 4bytes,小于 8,因此 4bytes 将用于对齐。

Why memory layout is the same and doesn't depend on the pack value?

不允许编译器对结构成员重新排序,但可以填充成员。如果是 pack 8,它会执行以下操作;

#pragma pack(push, 8)    // largest element is 4bytes so it will be used instead of 8
struct str_test
{
    unsigned int n; // 4 bytes
    unsigned short s; // 2 bytes        
    unsigned char b[4]; // 4 bytes
    //2 bytes padding here;
};
#pragma pack(pop)

因此 sizeof(str_test) 将为 12。

好吧,编译器 (MSVC2010) 似乎根据类型更改填充位置,在 unsigned char b[4]; 的情况下,它在结构的末尾放置了两个字节填充。在您的情况下,2 个字节 cc cc 恰好在字符数组之后。

#pragma pack(push, 8)    // largest element is 4bytes so it will be used instead of 8
struct str_test
{
    unsigned int n; // 4 bytes
    unsigned short s; // 2 bytes 
    //2 bytes padding here;       
    int;  // 4 bytes

};
#pragma pack(pop)

我所做的是将最后一个成员从 char[4] 更改为 int,并且可以通过在这两种情况下减去最后一个和第一个成员的地址来验证分别为 6 和 8。

最后一个成员int情况下的内存转储如下

04 03 02 01 a2 a1 cc cc f0 f1 f2 f3

最后一个成员unsigned char[4]情况下的内存转储如下

04 03 02 01 a2 a1 f0 f1 f2 f3 cc cc

关于c++ - 结构大小和内存布局取决于#pragma pack,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22475423/

有关c++ - 结构大小和内存布局取决于#pragma pack的更多相关文章

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

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

  2. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

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

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

  4. ruby-on-rails - Ruby 中的内存模型 - 2

    ruby如何管理内存。例如:如果我们在执行过程中采用C程序,则以下是内存模型。类似于这个ruby如何处理内存。C:__________________|||stack|||------------------||||------------------|||||Heap|||||__________________|||data|__________________|text|__________________Ruby:? 最佳答案 Ruby中没有“内存”这样的东西。Class#allocate分配一个对象并返回该对象。这就是程序

  5. ruby - 是否有用于序列化和反序列化各种格式的对象层次结构的模式? - 2

    给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最

  6. ruby - nanoc 和多种布局 - 2

    是否可以为特定(或所有)项目使用多个布局?例如,我有几个项目,我想对其应用两种不同的布局。一个是绿色的,一个是蓝色的(但是)。我想将它们编译到我的输出目录中的两个不同文件夹中(例如v1和v2)。我一直在玩弄规则和编译block,但我不知道这是怎么回事。因为,每个项目在编译过程中只编译一次,我不能告诉nanoc第一次用layout1编译,第二次用layout2编译。我试过这样的东西,但它导致输出文件损坏。compile'*'doifitem.binary?#don’tfilterbinaryitemselsefilter:erblayout'layout1'layout'layout2'

  7. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  8. ruby-on-rails - 一般建议和推荐的文件夹结构 - Sinatra - 2

    您将如何构建一个简单的Sinatra应用程序?我正在制作,我希望该应用具有以下功能:“应用程序”更像是一个包含所有信息的管理仪表板。然后另一个应用程序将通过REST访问信息。我还没有创建仪表板,只是从数据库中获取东西session和身份验证(尚未实现)您可以上传图片,其他应用可以显示这些图片我已经使用RSpec创建了一个测试文件通过Prawn生成报告目前的设置是这样的:app.rbtest_app.rb因为我实际上只有应用程序和测试文件。到目前为止,我已经将Datamapper用于ORM,将SQLite用于数据库。这是我的第一个Ruby/Sinatra项目,所以欢迎任何和所有建议-我应

  9. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  10. 键删除后 ruby​​ 哈希内存泄漏 - 2

    你好,我无法成功如何在散列中删除key后释放内存。当我从哈希中删除键时,内存不会释放,也不会在手动调用GC.start后释放。当从Hash中删除键并且这些对象在某处泄漏时,这是预期的行为还是GC不释放内存?如何在Ruby中删除Hash中的键并在内存中取消分配它?例子:irb(main):001:0>`ps-orss=-p#{Process.pid}`.to_i=>4748irb(main):002:0>a={}=>{}irb(main):003:0>1000000.times{|i|a[i]="test#{i}"}=>1000000irb(main):004:0>`ps-orss=-p

随机推荐