MacOS运行Gamit track模块时出现dyld libSystem.B.dylib Library not loaded错误
MacOS运行Gamit track模块时出现dyld libSystem.B.dylib Library not loaded错误
Astrophel问题描述
在使用MacOS版本的Gamit软件的track模块时,会出现类似错误:
1 | dyld[xxxx]: dyld cache '(null)' not loaded: syscall to map cache into shared region failed |
导致track模块无法正常运行。官方文档仅说明是由于Apple Silicon内存限制所造成的,并未给出具体原因及解决方法。
原因探究
通过查询Apple的帮助文档,结合一位Apple DTS工程师的说法,这背后其实有着悠久的历史(?
早在 Mac OS X 发布之初,Apple还不支持 SDK。当安装开发者工具时,它会在当前系统的绝对位置放置头文件,例如, 头文件将放置在 /usr/include/pcap/pcap.h,工具会在这些绝对位置查找头文件。同样的情况也会发生在库中,只不过链接器会在 /usr/lib 中查找。到目前为止,Unix系统仍然遵循这套规则。
但是这种方法在Apple工程师看来是“无稽之谈”,因为随着Apple设备向跨平台的方向发展,在macOS 上发布iOS库毫无意义,因为它只是一堆无法执行的代码。所以,Apple使用了一种 dynamic linker shared cache
共享缓存技术来取代dylib库。这本意是好的,但是,当Mac转向Apple Silicon后,问题就出现了。
由于磁盘中的标准库,例如本文中的libSystem.B.dylib
被存放在了共享缓存中,每次执行需要该库的可执行程序,该缓存都会被加载到一个固定的内存地址范围中,然后在运行可执行文件时由dyld链接。但是,如果你的可执行文件太大,以至于扩展到了共享缓存的地址范围,共享缓存自然就会报错无法执行了。在英特尔 Mac 上不会出现这个问题,因为在英特尔Mac上,这个固定的地址要大得多。
不巧的是,Gamit的老旧代码在今天看来存在诸多问题,其track模块中定义了一个巨大的静态数组,大小远远超过了Mac共享缓存机制的最大内存限制(1.993 GB)。所以,调用track时,内存中的共享缓存被其覆盖,动态链接库libSystem.B.dylib自然也就找不到了。
解决方案
很显然,从根源上解决该问题的方式是避免使用如此庞大的静态数组,利用MALLOC
或ALLOCATE
动态分配内存空间——但这对于我们普通用户来说是不现实的。
参考课程老师的意见,选择修改“~/gg/opt/gamit10.71/kf/track/track_com.h”
头文件中最大测站数和最大历元数:
在文件约47行,将几个数组的定义修改为:
1 | parameter ( max_site = 5 ) |
也可以修改为其他值,只要小于1.993 GB即可。
然后删除“~/gg/opt/gamit10.71/kf/track“
目录下的可执行程序“track”和库文件“track_lib.a”,重新在该目录终端中执行sudo make
进行编译。编译结束后即可即可正常使用track模块。
p.s. 虽然原理不同,但该解决方案也可以解决ubuntu系统中因内存不足引起的“段错误”问题。
参考文献
[1] My libSystem.B.dylib is Missing from my Mac|Apple developer forums
[2] A DTS Engineer‘s Answer from Apple|Apple developer forums