【发布时间】:2010-10-07 14:00:44
【问题描述】:
有人可以提供一个示例,由于未对齐而将指针从一种类型转换为另一种类型失败吗?
在this answer 的 cmets 中,bothie 表示正在做类似的事情
char * foo = ...;
int bar = *(int *)foo;
如果启用对齐检查,即使在 x86 上也可能会导致错误。
我尝试在 GDB 中通过set $ps |= (1<<18) 设置对齐检查标志后产生错误条件,但什么也没发生。
工作(即不工作;))示例是什么样的?
答案中的所有代码 sn-ps 在我的系统上都没有失败 - 我稍后会在不同的编译器版本和不同的电脑上尝试它。
顺便说一句,我自己的测试代码是这样的(现在也使用 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 和 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 上的失败...
【问题讨论】:
-
该代码将崩溃并烧毁 x86 系统(SPARC、PPC,可能是 IA64,除非将其设置为容错)。
-
不是编译器或操作系统,而是 x86 - 它非常容忍这个错误。查看迈克尔·伯尔的回答
-
@Mark:那么其他人是否认为会出现错误?
-
Christoph,您检查过反汇编并尝试逐步完成吗?
-
@codelogic:是的,我有 - 未对齐的访问肯定存在:
mov -0x17(%ebp), %edx
标签: c pointers alignment casting