使用虚拟继承的地址未对齐

2023-11-23

以下明显有效的代码使用 UndefinedBehaviorSanitizer 清理程序产生未对齐的地址运行时错误。

#include <memory>
#include <functional>

struct A{
  std::function<void()> data; // seems to occur only if data is a std::function
} ;

struct B{
  char data; // occurs only if B contains a member variable
};

struct C:public virtual A,public B{

};

struct D:public virtual C{

};

void test(){
  std::make_shared<D>();
}

int main(){
  test();
  return 0;
}

在 macbook 上编译并执行clang++ -fsanitize=undefined --std=c++11 ./test.cpp && ./a.out产生输出runtime error: constructor call on misaligned address 0x7fe584500028 for type 'C', which requires 16 byte alignment [...].

我想了解错误发生的方式和原因。


由于对齐std::function<void()>是 16,大小是 48 让我们简化一下。这段代码有同样的行为但更容易理解:

struct alignas(16) A
{ char data[48]; };

struct B
{ char data; };

struct C : public virtual A, public B
{};

struct D : public virtual C
{};

int main()
{
    D();
}

我们有以下对齐方式和尺寸:

                     |__A__|__B__|__C__|__D__|
 alignment (bytes):  |  16 |  1  |  16 |  16 |
      size (bytes):  |  48 |  1  |  64 |  80 |

现在让我们看看这在内存中是什么样子的。对此的更多解释可以在这个很好的答案.

  • A: char[48] + no padding == 48B
  • B: char[1] + no padding == 1B
  • C: A* + B + A + 7 bytes of padding (align to 16) == 64B
  • D: C* + C + 8 bytes of padding (align to 16) == 80B

现在很容易看出偏移量C inside D是8个字节,但是C与 16 对齐。因此错误,伴随着这个伪图形

00 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00
             ^ 

这里每个零是 1 个字节。

UPDATE: 在何处以及如何放置填充取决于 C++ 编译器。标准没有明确规定。它看起来像填充的大小,clang 无法对齐所有内容D。减轻错位的一种方法是仔细设计类,使它们具有相同的对齐方式(例如 8 字节)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用虚拟继承的地址未对齐 的相关文章

随机推荐

  • Azure Keyvault 通过 ARM 添加功能 MSI

    我认为托管服务身份是一个很棒的概念 我喜欢 keyvault 然而 当我使用增量资源组部署的脚本时 为简洁起见 对示例进行了修改 type Microsoft KeyVault vaults name parameters keyvault
  • C# Xamarin OnClick 函数

    我正在做的是这个 Button button1 FindViewById
  • 如何以编程方式调整 ImageView 的大小

    我想在触摸 ImageView 时调整它的大小 就像在谷歌地图或移动浏览器中进行缩放一样 调整它的大小将是完美的 但如果只是触摸它 我可以调整它的大小就足够了 那可能吗 只需捕获触摸此 ImageView 的事件 然后调整高度和重量即可 t
  • 小时数相加或求和,例如 13:30+00:00:20=13:30:20 但如何呢?

    我想在日期时间值 可能存储字符串类型 上添加秒 00 00 02 或分钟 00 00 20 但是如何添加 例子 13 30 02 02 02 15 32 02 13 30 00 00 01 13 30 01 13 30 00 01 00 1
  • 将隐藏输入作为字符串抓取(使用 PHP 简单 HTML DOM 解析器)

    所以我有一个有 4 个输入 2 个文本 2 个隐藏的表单 我从名称中获取了两个文本输入值 即 get me two get me third 并且还获取了表单操作 get me php 我现在要做的是获取 2 个隐藏输入 而不是值 我想自己
  • Varchar(max) 列不允许作为 SQL Server 中的主键

    Varchar max 列不允许作为 SQL Server 中的主键 可以作为主键的 varchar 类型的最大长度是多少 这可能是一个不好的做法 但遇到了这种情况 900 字节是主键的最大长度 在我看来这是一个坏主意 为什么不使用代理键呢
  • 获取python程序的退出代码

    我正在 WindowsXP 上运行 python 程序 程序结束后如何获取退出代码 从 Windows 命令行 您可以使用 echo ERRORLEVEL 例如 C work gt python helloworld py Hello Wo
  • flutter 异步验证表单

    new TextFormField validator value async if value isEmpty return Username is required if await checkUser return Username
  • Angular-CLI 代理到后端不起作用

    https github com angular angular cli proxy to backend这是如何对后端进行代理的说明 我一步一步完成了所有操作 但请求仍然没有被代理 8080 我的 Express 后端 4200 我的 A
  • 无法自动装配服务

    我正在尝试从 FOSUserBundle Symfony3 4 实现 UserManager 服务 注册 php
  • 可在网络上打印的大型 PDF

    问题 我有一个 35mb 的 PDF 文件 共 130 页 我需要将其放到网上 以便人们每周可以打印其中的不同部分 我现在在 Amazon S3 上托管 PDF 文件 并被告知用户不喜欢在选择要打印的页面之前等待整个文件下载 我想我必须发挥
  • WPF:如何禁用选项卡导航而不同时禁用箭头键导航?

    我已经设定IsTabStop在我的窗口中的所有控件上设置为 false 这样当我按 Tab 键时 焦点不会移动 我需要 Tab 键来执行其他操作 但是这样做会破坏箭头键导航 我单击 a 中的一个项目ListView然后按向上 向下不会再更改
  • Git 贡献未显示在 GitHub 上

    我浏览了你的以下文章https help github com articles why are my contributions not showing up on my profile 因为贡献没有显示在我的个人资料上 至少可以说 我正
  • Java List 到 Map 转换

    我想转换一个Map
  • 为 C++ 库制作 Objective-C 包装器

    我正在尝试用 Objective C 制作一个包装器 这样我就不必在库类之外编写 C 了 库的主文件是LLAHProcessor h cpp 我的包装是LLAHProcessorWrapper h mm 它编译得很好 但是当我添加LLAHP
  • html/templates - 用
    替换换行符

    我正在加载一个包含换行符的文本文件 并将其传递给html templates 替换为 n with br 在加载的字符串中 它们被模板转义为 html lt br gt 并显示在浏览器中 而不是导致行返回 我怎样才能改变这种行为而不切换到t
  • Placeholder_2:0 既被馈送又被提取

    当我运行这段代码时 x tf placeholder tf int32 shape None 3 with tf Session as sess feed dict dict feed dict x np array 1 2 3 4 5 6
  • 如何将 GestureDetector 附加到 ListPreference?

    附加一个的挑战手势检测器 to a 列表首选项是 2 倍 获取仅在preferences xml中定义的ListPreference的句柄 即未在Java代码中实例化 ListPreference 既不是 View 也不是 Activity
  • GLFW3 - 对 XRR 的未定义引用

    我正在尝试编译一个非常简单的OpenGL程序使用 GLFW3 尽管链接了我认为必要的所有内容 但我还是收到了大量未定义的引用 usr local lib libglfw3 a x11 gamma c o In function glfwIn
  • 使用虚拟继承的地址未对齐

    以下明显有效的代码使用 UndefinedBehaviorSanitizer 清理程序产生未对齐的地址运行时错误 include