x86 上未对齐的指针 [英] Mis-aligned pointers on x86

查看:26
本文介绍了x86 上未对齐的指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Can someone provide an example were casting a pointer from one type to another fails due to mis-alignment?

在对这个答案的评论中,bothie 声明做类似的事情

In the comments to this answer, bothie states that doing something like

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

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

might lead to errors even on x86 if alignment-checking is enabled.

在 GDB 中通过 set $ps |= (1<<18) 设置对齐检查标志后,我尝试产生错误条件,但没有任何反应.

I tried to produce an error condition after setting the alignment-check flag via set $ps |= (1<<18) in GDB, but nothing happened.

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

What does a working (ie non-working ;)) example look like?

答案中的所有代码片段都没有在我的系统上失败 - 我稍后会在不同的编译器版本和不同的 PC 上进行尝试.

None of the code snippets from the answers fail on my system - I'll try it with a different compiler version and on a different pc later.

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

Btw, my own test code looked like this (now also using asm to set AC flag and unaligned read and write):

#include <assert.h>

int main(void)
{
    #ifndef NOASM
    __asm__(
        "pushf
"
        "orl $(1<<18),(%esp)
"
        "popf
"
    );
    #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), %edxmovl $0xf1f2f3f4,-0x17(%ebp).

The assertion passes without problems, even though the generated code definitely contains the unaligned access mov -0x17(%ebp), %edx and movl $0xf1f2f3f4,-0x17(%ebp).

那么设置AC是否会触发SIGBUS?我无法在 Windows XP 下的英特尔双核笔记本电脑上使用我测试的 GCC 版本(MinGW-3.4.5、MinGW-4.3.0、Cygwin-3.4.4),而 codelogic 和 Jonathan Leffler提到 x86 上的失败...

So will setting AC trigger a SIGBUS or not? I couldn't get it to work on my Intel dual core laptop under Windows XP with none of the GCC versions I tested (MinGW-3.4.5, MinGW-4.3.0, Cygwin-3.4.4), whereas codelogic and Jonathan Leffler mentioned failures on x86...

推荐答案

EFLAGS.AC 要真正生效,还有一个没有提到的附加条件.必须设置 CR0.AM 以防止 INT 17h 在 486 之前没有处理此异常的旧操作系统上跳闸.不幸的是,Windows 默认没有设置它,你需要编写一个内核模式的驱动程序来设置它.

There is an additional condition, not mentioned, for EFLAGS.AC to actually take effect. CR0.AM must be set to prevent INT 17h from tripping on older OSes predating the 486 that have no handler for this exception. Unfortunately, Windows do not set it by default, you need to write a kernel-mode driver to set it.

这篇关于x86 上未对齐的指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆