我们假设,我有一个C结构DynApiArg_t
。
typedef struct DynApiArg_s { uint32_t m1; ... uint32_t mx; } DynApiArg_t;
这个结构的指针作为一个parameter passing给一个函数
void DynLibApi(DynApiArg_t *arg) { arg->m1 = 0; another_fn_in_the_lib(arg->mold); /* May crash here. (1) */ }
它存在于dynamic库libdyn.so
。 这个API是通过调用的dlopen/dlsym
过程从可执行文件调用的。
如果这个dynamic库更新到版本2,其中DynApiArg_t
现在有新的成员,如m2
,如下所示:
typedef struct DynApiArg_s { uint32_t m1; OldMbr_t *mold; ... uint32_t mx; uint32_t m2; NewMbr *mnew; } DynApiArg_t;
如果没有通过dlopen/dlsym
调用此API的可执行文件或其他库的完整重build,则每次调用此API时,都会看到进程崩溃,这是由于struct中的任何成员的一些取消引用。 我知道访问M2可能是一个问题。 但是看到像下面的成员mold
被视为导致崩溃。
typedef void (*fnPtr_t)(DynApiArg_t*); void DynApiCaller(DynApiArg_t *arg) { void *libhdl = dlopen("libdyn.so", RTLD_LAZY | RTLD_GLOBAL); fnPtr_t fptr = dlsym(libhdl, "DynLibApi"); fnptr(arg); /* actual call to the dynamically loaded API (2) */ }
在通过fnptr调用API时,在标记(2)的行处,当在(1)处访问旧/现有成员(在v1的v1中,当DynApiCaller初始编译时),它恰好是任何垃圾值,甚至有时候是NULL
。
每次更新依赖库时,如果没有对可执行文件进行完整的重新编译,处理这种更新的正确方法是什么?
我已经看到libs被命名为与libsolid.so.4等版本号。 有什么与这个版本控制系统有关的东西可以帮助我吗? 如果是的话,你可以指出我的权利文件,如果有的话?