我有两个插件
pluginA.plugin
和 pluginB.plugin
,它们都依赖于同一个库 libC.dylib
。构建插件时,我会递归地检查动态依赖项(使用 otool -L
),复制每个插件的 libs
文件夹内的所有依赖项,并使用 install_name_tool
调整依赖项路径,即“随身携带我所有的东西”方法。
我试图了解当某些程序加载这两个插件时会发生什么?
libC.dylib
会被加载两次而导致运行时崩溃吗?或者运行时是否会意识到同一个 dylib 有两个副本(基于版本?)并只使用一个?
动态库搜索和加载的顺序在Apple的动态库使用指南
中有描述简而言之,如果插件中依赖库的路径匹配,则该库将仅加载一次。在每次下一次加载时,只会增加内部计数器:
dlopen 函数返回与在 第一次调用,但它也会增加与关联的引用计数 手柄
如果库的路径不同,则将加载库的不同副本。
注意:在检查库是否已加载时,使用它的绝对路径。它可以直接设置依赖关系,在全局目录中搜索期间发现或从@rpath解析。
关于符号解析期间的潜在冲突:
未发现动态共享库之间的名称冲突 编译时、链接时或运行时。 dlsym 函数使用字符串 匹配来查找符号。如果两个库使用相同的名称 函数时,动态加载器返回第一个匹配的 赋予 dlsym 的符号名称。
因此,如果两个插件使用相同的库,多个副本不会使程序崩溃。如果他们期望同名下有不同的库,那就是一个大问题,你应该使用版本兼容机制 - 请参阅动态库设计指南