“总线错误”消息是什么意思,它与分段错误有什么不同?


当前回答

总线错误的一个典型实例是在某些体系结构上,例如SPARC(至少在某些SPARC上,可能已经更改了),即当您执行不一致的访问时。例如:

unsigned char data[6];
(unsigned int *) (data + 2) = 0xdeadf00d;

这段代码尝试将32位整型值0xdeadf00d写入(很可能)没有正确对齐的地址,并将在“挑剔”的体系结构上生成总线错误。顺便说一下,Intel x86并不是这样的架构。它将允许访问(尽管执行速度较慢)。

其他回答

它通常表示未对齐的访问。

试图访问物理上不存在的内存也会产生总线错误,但如果您使用的是带有MMU的处理器和没有bug的操作系统,则不会看到这个错误,因为您不会将任何不存在的内存映射到进程的地址空间。

首先,SIGBUS和SIGSEGV不是特定类型的错误,而是错误组或错误族。这就是为什么您通常会看到一个信号数(si_no)和一个信号代码(si_code)。

它们还取决于操作系统和体系结构,具体是什么导致了它们。

一般来说我们可以这么说。 SIGSEGV与内存映射(权限,无映射)相关,即mmu错误。

SIGBUS是当内存映射成功时,你遇到了底层内存系统的问题(内存不足,该位置没有内存,对齐,smmu阻止访问等),即总线错误。

一个SIGBUS也可以与mmap文件,如果文件从系统中消失,例如,你mmap文件在一个可移动媒体上,它被拔出。

查看平台的一个好地方是siginfo.h标头,以了解信号子类型。 这个页面提供了一个概述。 https://elixir.bootlin.com/linux/latest/source/include/uapi/asm-generic/siginfo.h#L245

/*
 * SIGSEGV si_codes
 */
#define SEGV_MAPERR 1   /* address not mapped to object */
#define SEGV_ACCERR 2   /* invalid permissions for mapped object */
#define SEGV_BNDERR 3   /* failed address bound checks */
#ifdef __ia64__
# define __SEGV_PSTKOVF 4   /* paragraph stack overflow */
#else
# define SEGV_PKUERR    4   /* failed protection key checks */
#endif
#define SEGV_ACCADI 5   /* ADI not enabled for mapped object */
#define SEGV_ADIDERR    6   /* Disrupting MCD error */
#define SEGV_ADIPERR    7   /* Precise MCD exception */
#define SEGV_MTEAERR    8   /* Asynchronous ARM MTE error */
#define SEGV_MTESERR    9   /* Synchronous ARM MTE exception */
#define NSIGSEGV    9

/*
 * SIGBUS si_codes
 */
#define BUS_ADRALN  1   /* invalid address alignment */
#define BUS_ADRERR  2   /* non-existent physical address */
#define BUS_OBJERR  3   /* object specific hardware error */
/* hardware memory error consumed on a machine check: action required */
#define BUS_MCEERR_AR   4
/* hardware memory error detected in process but not consumed: action optional*/
#define BUS_MCEERR_AO   5
#define NSIGBUS     5

最后需要注意的是,所有信号都可以由用户生成,例如kill。 如果它是用户生成的,那么si_code就是SI_USER。所以特殊源得到负si_codes。

/*
 * si_code values
 * Digital reserves positive values for kernel-generated signals.
 */
#define SI_USER     0       /* sent by kill, sigsend, raise */
#define SI_KERNEL   0x80        /* sent by the kernel from somewhere */
#define SI_QUEUE    -1      /* sent by sigqueue */
#define SI_TIMER    -2      /* sent by timer expiration */
#define SI_MESGQ    -3      /* sent by real time mesq state change */
#define SI_ASYNCIO  -4      /* sent by AIO completion */
#define SI_SIGIO    -5      /* sent by queued SIGIO */
#define SI_TKILL    -6      /* sent by tkill system call */
#define SI_DETHREAD -7      /* sent by execve() killing subsidiary threads */
#define SI_ASYNCNL  -60     /* sent by glibc async name lookup completion */

#define SI_FROMUSER(siptr)  ((siptr)->si_code <= 0)
#define SI_FROMKERNEL(siptr)    ((siptr)->si_code > 0)

这取决于你的操作系统、CPU、编译器以及其他因素。

一般来说,这意味着CPU总线无法完成命令或发生冲突,但这可能意味着一系列事情,具体取决于正在运行的环境和代码。

段错误是访问不允许访问的内存。它是只读的,你没有权限等等。

总线错误试图访问不可能存在的内存。您使用了一个对系统没有意义的地址,或者该操作的地址类型是错误的。

我相信内核会引发SIGBUS 当应用程序显示数据时 数据总线上的不对中。我认为 那是因为大多数[?现代编译器 对于大多数处理器,垫/对齐 为程序员提供的数据 以前的对准问题(至少) 减轻,因此一个人看不见 这些天SIGBUS太频繁(AFAIK)。

来自:这里