代码之家  ›  专栏  ›  技术社区  ›  0.sh

假定会导致总线错误的代码块执行良好

  •  3
  • 0.sh  · 技术社区  · 7 年前

    我目前正在阅读C编程专家Mign-Deep C Secrets。在第164页,作者解释了总线错误和分段错误,他展示了这行代码

    union { 
      char a[10];
      int i;
    } u ;
    
    int * p = ( int * ) &(u.a[1]);
    *p = 17; /* the misaligned addr in p causes a bus error */
    

    假设上面的代码触发了一个总线错误,但是当我运行它时,它运行得很好,没有任何错误。作者作了如下解释

    我对上述声明的理解是, char int char a[10]

    我的问题是为什么上面的代码没有导致总线错误。

    注:

    注: 已经提出了一个看起来与这个问题相像的问题,但我只针对上面的代码块。

    3 回复  |  直到 7 年前
        1
  •  9
  •   Ulrich Eckhardt    7 年前

    我认为这本书是错的。该代码导致未定义的行为。因此,期望它做出任何特定的行为都是有缺陷的。还请注意,并非所有体系结构都会导致总线错误。如果这本书没有解释这个事实,那也不能说明问题。

        2
  •  2
  •   a3f    7 年前

    我对上述语句的理解是,char是1字节,我们试图在char a[10]的索引上放置一个4字节的int,因此会发生总线错误(我不确定我的理解是否正确)

    char int

    如果您不遵守这一点,处理器可能会读取错误的数据或以异常惩罚您。然后,操作系统可以使用多个对齐的访问来模拟它,或者将其作为一个整体进行传递 SIGBUS 到用户应用程序。后者可能是作者在他的设置中所经历的。

    这一切与C有什么关系?

    你所拥有的是未定义的行为。处理器、内存控制器、编译器、操作系统和你附近的鼻腔恶魔的相互作用都会影响到它的效果(如果有的话)。在您的计算机上,处理器可能支持本机的未对齐访问,因此它可以工作,但这仍然是您不能依赖的:它只是 未定义 . (尤其是在优化的情况下,这些东西可能会回来咬你。对我来说,Works不够好,无法编写定义良好的C代码!)

        3
  •  1
  •   Dipstick    7 年前

    注:这本书非常古老,谈论的是32位CPU。对于64位,您可能需要更改 int * p = ( int * ) &(u.a[1]); int * p = ( int * ) &(u.a[5]); 因此,所需的所有数据都不能在一次从对齐地址获取的内存中获得。

    在许多其他CPU体系结构(ARM、PowerPC、MIPS、较新的Intel体系结构)上,示例代码可能会导致如上所述的问题,但现在一些操作系统(如Linux)可以配置为自动捕获故障并执行“修复”,允许程序在没有出现问题的情况下继续运行。对于大多数程序来说,这可能会被用户忽略,但相当耗时,并且会在实时软件和驱动程序中造成实际问题。

    时间关键型代码通常根据编译的CPU体系结构有条件地编译为执行或不执行未对齐的访问。在linux中,伪文件“/proc/cpu/alignment”可用于控制内核行为和查看有关“修复程序”数量的统计信息。