“总线错误”消息是什么意思,它与分段错误有什么不同?
当前回答
首先,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)
其他回答
首先,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)
一个值得注意的原因是,如果您试图mmap用户空间不允许访问的/dev/mem区域,则会返回SIGBUS。
段错误是访问不允许访问的内存。它是只读的,你没有权限等等。
总线错误试图访问不可能存在的内存。您使用了一个对系统没有意义的地址,或者该操作的地址类型是错误的。
对于我来说,由于没有声明程序集返回到.text部分,我意外触发了“总线错误”。这似乎是显而易见的,但它让我困惑了一段时间。
Eg.
.globl _myGlobal # Allocate a 64-bit global with the value 2
.data
.align 3
_myGlobal:
.quad 2
.globl _main # Main function code
_main:
push %rbp
从数据返回代码时缺少一个文本指令:
_myGlobal:
.quad 2
.text # <- This
.globl _main
_main:
希望这能对某人有所帮助
总线错误现在在x86上很少见,发生在你的处理器甚至不能尝试请求的内存访问时,通常是:
使用具有不满足其对齐要求的地址的处理器指令。
分段错误发生在访问不属于你的进程的内存时。它们非常常见,通常是以下原因造成的:
使用指向已释放对象的指针。 使用未初始化的伪指针。 使用空指针。 缓冲区溢出。
PS:更准确地说,不是操作指针本身会导致问题。它正在访问它所指向的内存(解引用)。
推荐文章
- 如何生成一个核心转储在Linux上的分段错误?
- 在Python中如何在Linux和Windows中使用“/”(目录分隔符)?
- 使用sh shell比较字符串
- 为什么函数指针定义可以使用任意数量的&号或星号* ?
- 什么是可重入函数?
- 如何在C中将数组初始化为0 ?
- Typedef定长数组
- 只列出UNIX中的目录
- 在C语言中通过引用传递
- sizeof(某个指针)总是等于4吗?
- 为什么星号在变量名之前,而不是在类型之后?
- 如何限制从grep返回的结果的数量?
- 何时使用内联函数,何时不使用它?
- 如何管道列表的文件返回的找到命令到猫查看所有文件
- 以相对于当前目录的路径递归地在Linux CLI中列出文件