有时,在各种Unix体系结构中,在程序运行时重新编译程序会导致程序崩溃并显示“总线错误”。任何人都可以解释发生这种情况的条件吗首先,如何更新磁盘上的二进制文件对内存中的代码执行任何操作?我能想象的唯一情况是有些系统将代码映射到内存中,当编译器重写磁盘映像时,这会导致mmap无效。这种方法的好处是什么?通过更改可执行文件来使运行代码崩溃看起来非常不理想。重新编译二进制文件时发生总线错误
回答
在本地文件系统上,所有主流的类Unix系统都支持通过删除文件来解决此问题。旧的vnode保持打开状态,即使在目录条目消失之后重新用于新映像,旧文件仍然存在,未更改,现在未命名,直到最后一次引用它(在此情况下,内核)消失为止。
但是,如果你刚开始重写它,那么是的,它是mmap(3)'ed。当块被重写的两种情况之一可以取决于哪个MMAP发生(3)选项的动态链接程序使用:
- 内核将无效相应的页面,或
- 磁盘映像将改变,但现有的存储器页不会
无论哪种方式,正在运行的程序可能有麻烦。在第一种情况下,它基本上保证爆炸,而在第二种情况下,除非所有的页面都被引用,分页并且从不丢弃,否则它将被破坏。
有两个mmap标志旨在解决这个问题。一个是MAP_DENYWRITE(防止写入),另一个是MAP_COPY,它保留了原始版本的纯粹版本,并防止作者更改映射图像。
但是出于安全原因,DENYWRITE已被禁用,并且在任何主要的类Unix系统中都没有执行COPY。
这是一个有点复杂的情况,可能会发生在你的情况。这个错误的原因通常是内存对齐问题。总线错误在基于FreeBSD的系统中更常见。考虑一个场景,你有一个类似的结构,
struct MyStruct { char ch [29]; // 29字节 int32 i; // 4字节 }
所以这个结构的总大小应该是33个字节。现在考虑一个你有32字节缓存行的系统。此结构不能加载到单个缓存行中。现在考虑以下语句
Struct MyStruct abc; char * cptr = &abc; //结构起始处的char点指向 int32 * iptr =(cptr + 1)// iptr指向结构的第2个字节。
现在总体结构大小为33字节,您的int指针指向第2个字节,因此您可以从int指针读取32字节数据(因为分配的内存总大小为33字节)。但是当你尝试读取它时,如果结构被分配在缓存线的边界,那么操作系统不可能在一次调用中读取32个字节。由于当前缓存行仅包含31个字节的数据,其余1个字节位于下一个缓存行。这将导致一个无效的地址,并会给“布斯错误”。大多数操作系统通过在内部生成两个内存读取调用来处理这种情况,但一些Unix系统不处理这种情况。为避免这种情况,建议您注意内存对齐。大多数情况下,当您尝试将结构转换为另一种数据类型并尝试读取该结构的内存时,会发生这种情况。
该情况有点复杂,所以我不确定我是否可以用更简单的方式解释它。我希望你了解这种情况。
感谢您的回答,但我不明白这与更改磁盘上的映像有何关系。代码运行良好,除非我在可执行文件运行时重新编译它。 – Lutorm 2011-03-10 18:55:29
- 1. C++ - 读取二进制文件错误或编译器错误?
- 2. 编译二进制文件
- 3. C++:二进制搜索编译错误
- 4. makefile - 在重新编译其他c文件时总是重新编译version.c
- 5. pip编译vs二进制文件
- 6. 如何编译二进制文件?
- 7. 编译为CSS时发生sass错误
- 8. 如何编译时发生错误
- 9. GCC编译的二进制文件给予 “不能执行二进制文件”
- 10. g ++编译的二进制文件给“不能执行二进制文件”
- 11. 开始从kaa下载二进制文件时发现错误
- 12. gdb:使用-g编译的二进制文件与使用-g编译的二进制编译的代码
- 13. 在SBT本地发布预编译X二进制文件
- 14. 编译器错误与二进制树复制构造函数
- 15. 在汇编内联编程中发生总线错误x86
- 16. 编译matlab linux二进制
- 17. LLVM编译JIT二进制
- 18. 错误膨胀二进制XML文件
- 19. Aws lambda二进制文件EACCES错误
- 20. 如何重新编码iPhone应用程序二进制文件?
- 21. JEDI控件总是重新编译
- 22. 将XML文件编译为二进制文件
- 23. 变化少进口的文件不会触发重新编译
- 24. 编辑时发生代码错误,但编译时很好
- 25. “错误:在C编译时发生'\ 342'”,“stray'\ 200'”,“stray'\ 234'”错误?
- 26. 解析二进制文件时出错
- 27. 内部编译器错误:总线错误与LLVM GCC 4.2编译
- 28. 读取二进制文件产生错误的输出
- 29. 在生产中缺少image_optim_pack的二进制文件错误
- 30. 生成二进制到二进制时出错
因此编译器一般不会删除和重写,而是覆盖输出文件? – Lutorm 2011-03-10 18:56:43