免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: iterator

修改指针值的操作是一个原子操作? [复制链接]

论坛徽章:
0
发表于 2008-05-19 13:17 |显示全部楼层
原帖由 iterator 于 2008-5-19 12:48 发表


那个str应该不是32位对齐的呀

对,我刚才想叉了,它没对齐到自然边界,按理是有问题的。
但我在RSIC平台上做了一个实验,在这个平台上,不对齐的访问会引发一个错误。非常意外的发现,结构体内的不对齐的指针赋值没有问题,但自己构造的未对齐指针赋值就有错。下面是程序和结果
1 #include <stdio.h>
  2 #include <stdlib.h>
  3
  4 struct p
  5 {
  6     char a;
7     char *str;               //这里的指针也没对齐到自然边界
  8     char b;
  9 } __attribute__ ((packed)) x;
10
11 int main()
12 {
13     char buf[10];
14     unsigned long addr = (unsigned long)&x.str;
15     int *pp = (int *)&buf[1];                 //这是个不对齐的数据访问
16     char **str = (char **)&buf[1];        //这个是个不对齐的指针

17
18     *pp = 100;                 //出错
19     *str = "hello";            //出错

20     printf("%d,%#lx\n", sizeof(x), addr);
21     x.str = "hello";           //没问题
22     printf("%s\n", x.str);
23
24 }


下面是运行结果:
[xin@vti-build tmp]$ ./t_align
t_align(18426): unaligned access to 0x60000fffffffb6a1, ip=0x4000000000000690
t_align(18426): unaligned access to 0x60000fffffffb6a1, ip=0x40000000000006b1

10,0x60000fffffffb691
hello

注意3个地址都是奇数结尾的,都没对齐到自然边界,但结构体内那个操作没出错


糊涂了,大家有什么看法,我也再想想

论坛徽章:
0
发表于 2008-05-19 14:21 |显示全部楼层
原帖由 zx_wing 于 2008-5-19 13:17 发表

对,我刚才想叉了,它没对齐到自然边界,按理是有问题的。
但我在RSIC平台上做了一个实验,在这个平台上,不对齐的访问会引发一个错误。非常意外的发现,结构体内的不对齐的指针赋值没有问题,但自己构造的未 ...

对这个问题我研究了一下,通过反汇编,看出了问题
实际上x.str = "hello"; 这句,编译器保证了对齐访问。
策略可以用下面伪代码表示(我的机器是64bit的):
unsigned long addr = (unsigned long)"hello";
unsigned long first_write =  (addr >> 8) | (x.a << 56);
unsigned long sec_write = (addr << 8) | (x.b);

*(unsigned long *)&x = first_write;
*(unsigned long *)((void *)&x + 8) = sec_write;

可见,编译器用两次对齐到64bit边界的写操作完成了对未对齐到64bit边界的指针的赋值。
从中我们或许可以得到两个结论:
1、在对齐要求严格的平台上,编译器可以感知结构体内非对齐的访问,将它转换成对齐操作。
2、在x86平台上,未对齐到自然边界的指针赋值,应该是非原子的。

大家是对的哈,我前面的两个回复错了。

[ 本帖最后由 zx_wing 于 2008-5-19 15:11 编辑 ]

论坛徽章:
2
亥猪
日期:2014-03-19 16:36:35午马
日期:2014-11-23 23:48:46
发表于 2008-05-19 14:24 |显示全部楼层
>>>但我在RSIC平台上做了一个实验
与risc无关,依赖具体实现和编译器。

论坛徽章:
2
亥猪
日期:2014-03-19 16:36:35午马
日期:2014-11-23 23:48:46
发表于 2008-05-19 14:27 |显示全部楼层
*str = "hello";            //出错

???

论坛徽章:
0
发表于 2008-05-19 14:35 |显示全部楼层
原帖由 gvim 于 2008-5-19 14:24 发表
>>>但我在RSIC平台上做了一个实验
与risc无关,依赖具体实现和编译器。

有关系的,CISC平台,通常是x86,不会引起未对齐错误,因为是硬件自己处理
RISC平台,会产生一个未对齐的异常。通常会报告给出错的程序。
当然,我不知道是不是所有RISC平台都如此。

出错的情况我已经贴出来了。
版主如果在你的平台上发现不同,希望给出你的平台和编译器的行为
我已经解释了在IA64平台上,编译器如何处理。

论坛徽章:
0
发表于 2008-05-19 14:36 |显示全部楼层
原帖由 gvim 于 2008-5-19 14:27 发表
*str = "hello";            //出错

???

对,出错
t_align(18426): unaligned access to 0x60000fffffffb6a1, ip=0x4000000000000690
t_align(18426): unaligned access to 0x60000fffffffb6a1, ip=0x40000000000006b1
对应程序中的:
18     *pp = 100;                 //出错
19     *str = "hello";            //出错

论坛徽章:
2
亥猪
日期:2014-03-19 16:36:35午马
日期:2014-11-23 23:48:46
发表于 2008-05-19 15:44 |显示全部楼层
>>>RISC平台,会产生一个未对齐的异常。通常会报告给出错的程序。
arm926ej-s
并不是所有的RISC都会抱你说的“未对齐”错误。


>>>*str = "hello";
你可以把它注释掉看看有没有错误。*str引向一个unknown的东西,复值过去当然会错。

[ 本帖最后由 gvim 于 2008-5-19 15:45 编辑 ]

论坛徽章:
0
发表于 2008-05-19 16:37 |显示全部楼层
原帖由 gvim 于 2008-5-19 15:44 发表
>>>RISC平台,会产生一个未对齐的异常。通常会报告给出错的程序。
arm926ej-s
并不是所有的RISC都会抱你说的“未对齐”错误。


>>>*str = "hello";
你可以把它注释掉看看有没有错误。*str引向一个unkno ...

好的,看来不是所有RISC平台都要求严格对齐的。
注释掉当然没有错误。
*str指向的是buf[1]开始的8个字节内存区域。
给它赋值也就是写buf[1]开始的8个字节,该区域存在于栈上,我们写它完全是合法应用。
不是版主说的unkonw的区域哈,如果是那样,系统会产生segfault,而非未对齐错误。

**str="hello"才是版主说的引用unkonwn区域,而引起segfault。

[ 本帖最后由 zx_wing 于 2008-5-19 16:49 编辑 ]

论坛徽章:
0
发表于 2008-05-19 16:42 |显示全部楼层
原帖由 gvim 于 2008-5-19 15:44 发表
>>>RISC平台,会产生一个未对齐的异常。通常会报告给出错的程序。
arm926ej-s
并不是所有的RISC都会抱你说的“未对齐”错误。


>>>*str = "hello";
你可以把它注释掉看看有没有错误。*str引向一个unkno ...

好奇
arm926ej-s平台如何解决未对齐?
我听说arm也是要严格对齐的啊

论坛徽章:
2
亥猪
日期:2014-03-19 16:36:35午马
日期:2014-11-23 23:48:46
发表于 2008-05-19 17:03 |显示全部楼层
>>>*str指向的是buf[1]开始的8个字节内存区域。
呵呵,不好意思,是我自己没有初始化-_-;

>>>arm926ej-s平台如何解决未对齐?
也是靠编译器。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP