x86 上未对齐的指针

2024-05-18

有人可以提供一个示例,将指针从一种类型转换为另一种类型由于未对齐而失败吗?

在评论中这个答案 https://stackoverflow.com/questions/544928/reading-integer-size-bytes-from-a-char-array/544964#544964,博蒂说做类似的事情

char * foo = ...;
int bar = *(int *)foo;

如果启用对齐检查,即使在 x86 上也可能会导致错误。

我试图通过设置对齐检查标志后产生错误条件set $ps |= (1<<18)在GDB中,但什么也没发生。

工作(即非工作;))示例是什么样的?


答案中的代码片段在我的系统上都不会失败 - 我稍后将使用不同的编译器版本并在不同的电脑上尝试它。

顺便说一句,我自己的测试代码看起来像这样(现在也使用 asm 来设置AC标志和未对齐的读写):

#include <assert.h>

int main(void)
{
    #ifndef NOASM
    __asm__(
        "pushf\n"
        "orl $(1<<18),(%esp)\n"
        "popf\n"
    );
    #endif

    volatile unsigned char foo[] = { 1, 2, 3, 4, 5, 6 };
    volatile unsigned int bar = 0;

    bar = *(int *)(foo + 1);
    assert(bar == 0x05040302);

    bar = *(int *)(foo + 2);
    assert(bar == 0x06050403);

    *(int *)(foo + 1) = 0xf1f2f3f4;
    assert(foo[1] == 0xf4 && foo[2] == 0xf3 && foo[3] == 0xf2 &&
        foo[4] == 0xf1);

    return 0;
}

即使生成的代码肯定包含未对齐的访问,断言也可以顺利通过mov -0x17(%ebp), %edx and movl $0xf1f2f3f4,-0x17(%ebp).


设置也会如此AC触发一个SIGBUS或不?我无法让它在 Windows XP 下的 Intel 双核笔记本电脑上运行,并且没有我测试过的 GCC 版本(MinGW-3.4.5、MinGW-4.3.0、Cygwin-3.4.4),而 codelogic 和 Jonathan Leffler提到 x86 上的失败...


在 x86 上,未对齐的访问会导致问题(除了内存访问需要更长的时间之外),这种情况并不常见。以下是我听说过的一些:

  1. 您可能不会将此视为 x86 问题,但 SSE 操作会受益于对齐。对齐的数据可以用作存储源操作数来保存指令。未对齐加载指令,例如movups慢于movaps在 Nehalem 之前的微体系结构上,但在 Nehalem 及更高版本(以及 AMD Bulldozer 系列)上,未对齐的 16 字节加载/存储与未对齐的 8 字节加载/存储的效率大致相同;如果数据恰好在运行时对齐或没有跨越缓存行边界,则不会有任何惩罚,否则对缓存行分割的硬件支持会很高效。在 Skylake 之前,4k 分割非常昂贵(约 100 个周期)(像缓存行分割一样降至约 10 个周期)。看https://agner.org/optimize/ https://agner.org/optimize/和性能链接x86 标签维基 https://stackoverflow.com/tags/x86/info了解更多信息。

  2. 互锁操作(例如lock add [mem], eax) are very如果它们没有充分对齐,则速度会很慢,特别是当它们跨越缓存行边界时,因此它们不能只在 CPU 核心内使用缓存锁。在较旧的(有缺陷的)SMP 系统上,它们might实际上无法成为原子的(参见https://blogs.msdn.com/oldnewthing/archive/2004/08/30/222631.aspx https://blogs.msdn.com/oldnewthing/archive/2004/08/30/222631.aspx).

  3. Raymond Chen 讨论的另一种可能性是在处理具有硬件存储内存的设备时(诚然是一种奇怪的情况) -https://blogs.msdn.com/oldnewthing/archive/2004/08/27/221486.aspx https://blogs.msdn.com/oldnewthing/archive/2004/08/27/221486.aspx

  4. 我记得(但没有参考资料 - 所以我不确定这一点)跨越页面边界的未对齐访问也存在类似问题,也涉及页面错误。我看看是否可以找到这方面的参考。

在研究这个问题时我学到了一些新东西(我想知道“$ps |= (1<<18)“在几个地方提到了 GDB 命令)。我没有意识到 x86 CPU(似乎从 486 开始)有能力在执行未对齐的访问时引发异常。

来自 Jeffery Richter 的“Windows 编程应用程序,第四版”:

让我们仔细看看 x86 CPU 是如何处理数据对齐的。 x86 CPU 在其 EFLAGS 寄存器中包含一个特殊位标志,称为 AC(对齐检查)标志。默认情况下,当 CPU 首次通电时,该标志设置为零。当该标志为零时,CPU 会自动执行其必须执行的操作,以便成功访问未对齐的数据值。然而,如果该标志设置为 1,则每当尝试访问未对齐的数据时,CPU 都会发出 INT 17H 中断。 Windows 2000 和 Windows 98 的 x86 版本永远不会更改此 CPU 标志位。因此,当应用程序在 x86 处理器上运行时,您永远不会看到应用程序中发生数据错位异常。

这对我来说是新闻。

当然,访问未对齐的一个大问题是,当您最终去编译非 x86/x64 处理器的代码时,您最终必须跟踪并修复一大堆东西,因为几乎所有其他 32 位或更大的处理器处理器对对齐问题很敏感。

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

x86 上未对齐的指针 的相关文章

  • 在 LINQ 查询中返回不带时间的日期

    我正在编写一个查询 我想计算按日期联系我们的呼叫中心的次数 看起来很简单 但由于联系日期字段是日期时间字段 我得到了时间 因此当我按联系日期 时间 分组时 每个联系日期实例的计数为 1 所以 我想只按日期分组 而不按时间分组 下面是我用来查
  • .net dropdownlist对齐文本

    我正在尝试将 net 下拉列表中的文本向右对齐 使用 CssClass 我可以在 Firefox 中将文本向右对齐 IE 不会将文本右对齐 而是左对齐 我读到 IE 6 不支持这个 这是真的 我使用的是 IE7 但我的大多数用户将使用 IE
  • 模板类的不明确多重继承

    我有一个真实的情况 可以总结为以下示例 template lt typename ListenerType gt struct Notifier void add listener ListenerType struct TimeListe
  • Cygwin 下使用 CMake 编译库

    我一直在尝试使用 CMake 来编译 TinyXML 作为一种迷你项目 尝试学习 CMake 作为补充 我试图将其编译成动态库并自行安装 以便它可以工作 到目前为止 我已经设法编译和安装它 但它编译成 dll 和 dll a 让它工作的唯一
  • 为什么禁止在 constexpr 函数中使用 goto?

    C 14 对你能做什么和不能做什么有规则constexpr功能 其中一些 没有asm 没有静态变量 看起来相当合理 但标准也不允许goto in constexpr功能 即使它允许其他控制流机制 这种区别背后的原因是什么 我以为我们已经过去
  • 跨多个控件共享事件处理程序

    在我用 C 编写的 Windows 窗体应用程序中 我有一堆按钮 当用户的鼠标悬停在按钮上时 我希望按钮的边框发生变化 目前我有以下多个实例 每个按钮一个副本 private void btnStopServer MouseEnter ob
  • 如何在 WPF RichTextBox 中跟踪 TextPointer?

    我正在尝试了解 WPF RichTextBox 中的 TextPointer 类 我希望能够跟踪它们 以便我可以将信息与文本中的区域相关联 我目前正在使用一个非常简单的示例来尝试弄清楚发生了什么 在 PreviewKeyDown 事件中 我
  • c 中的错误:声明隐藏了全局范围内的变量

    当我尝试编译以下代码时 我收到此错误消息 错误 声明隐藏了全局范围内的变量 无效迭代器 节点 根 我不明白我到底在哪里隐藏或隐藏了之前声明的全局变量 我怎样才能解决这个问题 typedef node typedef struct node
  • C# 用数组封送结构体

    假设我有一个类似于 public struct MyStruct public float a 我想用一些自定义数组大小实例化一个这样的结构 在本例中假设为 2 然后我将其封送到字节数组中 MyStruct s new MyStruct s
  • .Net Core / 控制台应用程序 / 配置 / XML

    我第一次尝试使用新的 ConfigurationBuilder 和选项模式进入 Net Core 库 这里有很多很好的例子 https docs asp net en latest fundamentals configuration ht
  • A* 之间的差异 pA = 新 A;和 A* pA = 新 A();

    在 C 中 以下两个动态对象创建之间的确切区别是什么 A pA new A A pA new A 我做了一些测试 但似乎在这两种情况下 都调用了默认构造函数 并且仅调用了它 我正在寻找性能方面的任何差异 Thanks If A是 POD 类
  • 线程、进程和 Application.Exit()

    我的应用程序由主消息循环 GUI 和线程 Task Factory 组成 在线程中我调用一些第三方应用程序var p new Process 但是当我调用Application Exit 在消息循环中 我可以看到在线程中启动的进程仍在内存中
  • 初始化变量的不同方式

    在 C 中初始化变量有多种方法 int z 3 与 int 相同z 3 Is int z z 3 same as int z z 3 您可以使用 int z z 3 Or just int z 3 Or int z 3 Or int z i
  • 像“1$”这样的位置参数如何与 printf() 一起使用?

    By man I find printf d width num and printf 2 1 d width num 是等价的 但在我看来 第二种风格应该与以下相同 printf d num width 然而通过测试似乎man是对的 为什
  • 作为字符串的动态属性名称

    使用 DocumentDB 创建新文档时 我想设置属性名称动态地 目前我设置SomeProperty 像这样 await client CreateDocumentAsync dbs db colls x new SomeProperty
  • 已过时 - OpenCV 的错误模式

    我正在使用 OpenCV 1 进行一些图像处理 并且对 cvSetErrMode 函数 它是 CxCore 的一部分 感到困惑 OpenCV 具有三种错误模式 叶 调用错误处理程序后 程序终止 Parent 程序没有终止 但错误处理程序被调
  • 在Linux中使用C/C++获取机器序列号和CPU ID

    在Linux系统中如何获取机器序列号和CPU ID 示例代码受到高度赞赏 Here http lxr linux no linux v2 6 39 arch x86 include asm processor h L173Linux 内核似
  • 方法参数内的变量赋值

    我刚刚发现 通过发现错误 你可以这样做 string s 3 int i int TryParse s hello out i returns false 使用赋值的返回值是否合法 Obviously i is but is this th
  • 窗体最大化时自动缩放子控件

    有没有办法在最大化屏幕或更改分辨率时使 Windows 窗体上的所有内容自动缩放 我发现手动缩放它是正确的 但是当切换分辨率时我每次都必须更改它 this AutoScaleDimensions new System Drawing Siz
  • 将变量分配给另一个变量,并将一个变量的更改反映到另一个变量中

    是否可以将一个变量分配给另一个变量 并且当您更改第二个变量时 更改会瀑布式下降到第一个变量 像这样 int a 0 int b a b 1 现在 b 和 a 都 1 我问这个问题的原因是因为我有 4 个要跟踪的对象 并且我使用名为 curr

随机推荐

  • 如何在 Angular 4 中的 HTML 中包含或排除属性

    我正在使用 Angular 4 和 Angular 材料来构建一张桌子 我想要mat sort header有条件地添加到以下模板中
  • 为什么范围为“provided”的依赖项会隐藏 Maven 中的传递依赖项?

    我的 Maven 项目中有三个模块 这稍微简化了 model包含JPA注释的实体类 坚持实例化一个实体管理器并调用它的方法 应用创建类的实例model 设置一些值并将它们传递给坚持 model and 坚持显然取决于javax persis
  • Keras:多类 NLP 任务中 model.evaluate 与 model.predict 的准确性差异

    我正在使用以下代码在 keras 中为 NLP 任务训练一个简单模型 训练集 测试集和验证集的变量名称是不言自明的 该数据集有 19 个类 因此网络的最后一层有 19 个输出 标签也是 one hot 编码的 nb classes 19 m
  • Watir Webdriver 加载 Chrome 扩展

    我正在尝试使用 Watir 加载 chrome 扩展 但遇到了问题 我发现这个相关问题 能够启动带有 watir webdriver 加载扩展的 chrome https stackoverflow com questions 125867
  • 在 React 中将模板分离到外部文件

    我正在为客户开发 ReactJS 应用程序 我希望客户端能够自定义应用程序中的一些配置和模板 所以我创建了一个config js file window APP CONFIG url example com template item di
  • 在 JavaScript 函数的 Django 模板中转义字符串参数

    我有一个 JavaScript 函数 它返回一组对象 return Func id name 例如 我在传递包含引号的字符串时遇到问题 Dr Seuss ABC BOOk 是无效语法 I tried name safe 但无济于事 有什么解
  • 32 位到 64 位内联汇编移植

    我有一段 C 代码 在 GNU Linux 环境下用 g 编译 它加载一个函数指针 它如何执行并不重要 使用一些内联汇编将一些参数推送到堆栈上 然后调用该函数 代码如下 unsigned long stack 1 23 33 43 save
  • oracle ExecuteNonQuery 在 ASP.Net 上冻结

    我正在尝试使用 ASP C 和 CLR 4 5 中的 Oracle 连接来运行非查询 这是我的代码 string connectionString ConfigurationManager ConnectionStrings OracleC
  • 可能的透支:根元素绘制背景

    在我的应用程序中 Android 的 lints 上出现此警告 可能的过度绘制 根元素使用 drawable main 绘制背景 还绘制背景的主题 推断的主题是 android style Theme 我想知道如何纠正这个错误 因为在互联网
  • 为什么 C# Math.Ceiling 向下舍入?

    我今天过得很艰难 但有些事情不太对劲 在我的 C 代码中 我有这样的内容 Math Ceiling decimal this TotalRecordCount this PageSize Where int TotalRecordCount
  • 为什么我收到“找不到编译动态表达式所需的一种或多种类型。”?

    我有一个已更新的项目 NET 3 5 MVC v2 到 NET 4 0 MVC v3 当我尝试使用或设置时编译出现错误 ViewBag Title财产 找不到编译动态表达式所需的一种或多种类型 您是否缺少对 Microsoft CSharp
  • d3.event.translate 在触摸设备的缩放上包含 NaN

    我使用 d3 为我的 svg 编写了一个自定义缩放函数 如下所示 Zoom behavior function myzoom xpos d3 event translate 0 ypos d3 event translate 1 vis a
  • Process.Start 阻塞

    我正在调用 Process Start 但它会阻止当前线程 pInfo new ProcessStartInfo C Windows notepad exe Start process mProcess new Process mProce
  • const、span 和迭代器的问题

    我尝试编写一个按索引迭代容器的迭代器 AIt and a const It两者都允许更改容器的内容 AConst it and a const Const it两者都禁止更改容器的内容 之后 我尝试写一个span
  • 如何在布局编辑器中模拟沉浸式模式

    我想在布局编辑器中全屏查看我的布局 我正在使用 eclipse 插件 我已经通过选择隐藏了 ActionBar NoActionBar组合中的主题 但导航栏是一个不同的故事 AFAIK 它只能使用代码中的标志来隐藏 我需要在活动 xml 文
  • ng-include 和 ng-view 不同时加载

    下面是我的应用程序的结构 很简单 页眉和页脚是非常小的文件 而主页上的 ng view 要大得多 当我进入该页面时 我注意到了这一点 首先加载两个 ng include 然后 ng view 出现 页脚被推到底部 页脚闪烁大约 0 1 秒
  • 如何在不同版本的Google App Engine中使用自定义域名?

    我使用谷歌应用程序引擎作为我的 Android 和 Web 应用程序的服务器 我使用 Android Studio 开发了 Android 应用程序 并使用 Eclipse 开发了 Web 应用程序 我在应用程序引擎中部署了两个版本 第一个
  • 更改 Tk 标签小部件中单个单词的颜色

    我想更改 Tkinter 标签小部件中单个单词的字体颜色 我知道可以使用文本小部件来实现与我想要完成的类似的事情 例如使单词 YELLOW 显示为黄色 self text tag config tag yel fg clr yellow s
  • Validation.ErrorTemplate 的 Wpf 动态资源查找

    在我的 App xaml 中 我定义了一个资源Validation ErrorTemplate 这取决于动态BorderBrush资源 我打算定义独特的BorderBrush在我拥有的每个窗口以及窗口内的不同块内
  • x86 上未对齐的指针

    有人可以提供一个示例 将指针从一种类型转换为另一种类型由于未对齐而失败吗 在评论中这个答案 https stackoverflow com questions 544928 reading integer size bytes from a