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

如何从C程序访问共享对象(.so)中的全局变量?解决调用设置函数后变量未更新问题

问题分析与解决方案

嘿,我一眼就瞅出问题出在哪了——你头文件里的全局变量声明方式错了,导致test可执行文件和preload.so里各有一个独立的var,自然看不到修改效果!

为啥原来的代码不生效?

你在preload.h里写的int var;不是单纯的“告诉编译器有这个变量”,而是直接让编译器在每个包含这个头文件的编译单元里都创建一个var的实例。这就导致:

  • test.c包含头文件后,最终生成的test可执行文件里有自己的var;
  • preload.so里也有一个自己的var(不然你编译so的时候会报错);
  • 这俩var完全是两个不同的内存地址!setting()改的是so里的那个,而main用的是test自己的,当然看不到变化。

修复步骤

只需要调整声明和定义的位置,让test里的var指向so里的实例:

  • 修正头文件的变量声明
    把preload.h里的int var;改成extern声明,只做“告知存在”的作用,不创建变量:

    // preload.h
    extern int var;
    void setting(int x);
    
  • 在so的实现文件里定义变量
    到preload.c里真正定义这个全局变量,让so加载时分配内存:

    // preload.c
    #include "preload.h"
    
    // 这里才是var的真正定义,只会在so里生成一个实例
    int var;
    
    void setting(int x) {
        var = x;
    }
    
  • 简化test.c的代码
    因为头文件已经做了extern声明,test.c里不需要再重复写extern int var;了,直接用就行:

    // test.c
    #include "preload.h"
    #include <stdio.h> // 别忘了加这个,不然printf没法用
    
    int main(){
        int x = 42; // 随便设个测试值
        setting(x);
        printf("var的值是:%d\n", var); // 现在就能拿到so修改后的结果了
        return 0;
    }
    
  • 重新编译执行
    还是用你原来的编译和执行命令:

    gcc test.c -o test
    gcc -shared -fPIC preload.c -o preload.so -ldl
    LD_PRELOAD=$PWD/preload.so ./test
    

额外提醒

这种LD_PRELOAD动态注入的场景下,符号隔离是很容易踩的坑。如果多个模块(可执行/so)里有同名全局变量,默认情况下它们是独立的,除非你用extern明确声明要引用其他模块的变量。另外,头文件里永远不要定义变量,只做声明——这是C语言的基本规范,能避免很多类似的隐蔽问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 08:37:28