You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何卸载共享库后,其中全局变量的内存会被释放?

关于共享库卸载后全局变量失效的疑问解答
  • 你对共享库数据段的理解有个关键偏差:数据段的“复制”是写时复制(COW)机制,不是加载时就完成复制
    • 共享库加载时,进程地址空间会映射共享库的代码段和数据段,但数据段的映射属性是「只读+写时复制」。此时所有加载该库的进程共享同一份物理内存页。
    • 只有当你的进程对共享库的全局变量执行写入操作时,操作系统才会把对应的数据页复制一份到进程的私有内存空间,之后这个变量的地址才指向进程自己的内存区域。
  • 卸载共享库(比如调用dlclose())时的核心行为:
    • 如果进程从未修改过共享库的全局变量,该变量的地址依然指向共享库的原始数据页,卸载后操作系统会回收这些页,此时访问这个地址就会触发无效内存访问错误。
    • 如果进程已经修改过该全局变量,对应的数据页已经被复制到进程私有内存,卸载共享库不会影响这份私有内存,此时访问变量是完全正常的。

举个简单的验证例子:

// 共享库代码 libtest.c
int global_var = 0;

编译成共享库:gcc -shared -fPIC libtest.c -o libtest.so

// 主程序 main.c
#include <dlfcn.h>
#include <stdio.h>

int main() {
    void* handle = dlopen("./libtest.so", RTLD_NOW);
    int* global = dlsym(handle, "global_var");
    
    // 情况1:只读取不修改
    printf("Read global_var: %d\n", *global);
    dlclose(handle);
    // 这里访问会触发段错误,因为global指向的共享库页已被回收
    // printf("After dlclose: %d\n", *global);

    // 情况2:先修改再卸载
    handle = dlopen("./libtest.so", RTLD_NOW);
    global = dlsym(handle, "global_var");
    *global = 100; // 触发写时复制
    printf("Modified global_var: %d\n", *global);
    dlclose(handle);
    // 这里访问正常,因为变量已经在进程私有内存里
    printf("After dlclose: %d\n", *global);

    return 0;
}

编译主程序:gcc main.c -ldl -o main
运行后就能直观看到两种情况的差异。

内容的提问来源于stack exchange,提问作者SZYoo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 03:10:55