有时,在各种Unix架构上,当程序正在运行时重新编译程序会导致程序崩溃并出现“总线错误”。有人能解释在哪些情况下会发生这种情况吗?首先,更新磁盘上的二进制文件如何影响内存中的代码?我唯一能想到的是某些系统将代码映射到内存中,当编译器重写磁盘镜像时,这会导致映射失效。这种方法的优势是什么?通过更改可执行文件来使正在运行的代码崩溃似乎非常不优秀。
这是一个可能在您的情况下发生的复杂场景。这个错误的原因通常是内存对齐问题。总线错误在基于FreeBSD的系统中更为常见。考虑这样一种情况,你有一个结构体,像这样:
struct MyStruct { char ch[29]; // 29字节 int32 i; // 4字节 }
所以这个结构体的总大小是33字节。现在考虑一个有32字节缓存行的系统。这个结构体无法在单个缓存行中加载。现在考虑以下语句
Struct MyStruct abc; char *cptr = &abc // char point points at start of structure int32 *iptr = (cptr + 1) // iptr points at 2nd byte of structure.
现在总结构大小为33字节,您的int指针指向第2个字节,因此您可以从int指针读取32字节的数据(因为分配内存的总大小为33字节)。但是,当您尝试读取它时,如果该结构分配在缓存行的边界上,则操作系统无法在单个调用中读取32字节。因为当前缓存行仅包含31字节的数据,剩余的1字节位于下一个缓存行上。这将导致无效地址并出现“总线错误”。大多数操作系统通过在内部生成两个内存读取调用来处理此情况,但某些Unix系统不处理此情况。为避免此问题,建议注意内存对齐。当您尝试将结构强制转换为另一种数据类型并尝试读取该结构的内存时,通常会发生这种情况。
这种情况有点复杂,所以我不确定是否能以更简单的方式解释它。希望您能理解这种情况。