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

为何无法在可执行文件内部通过dlopen/dlsym动态调用自身函数?

可执行文件内部动态调用同文件函数失败的解决方法

问题描述

尝试在可执行文件内部通过dlopen+dlsym动态调用同源码文件中的test_func函数,示例代码如下:

#include <stdio.h>
#include <dlfcn.h>

// or with some tricks
// void __attribute__((visibility("default")))
void test_func(void)
{
    printf("test_func in %s\n",__FILE__);
}

int main()
{
    void *handle = dlopen(0, RTLD_LAZY); // or RTLD_GLOBAL
    printf("dlopen return %p\n", handle);

    void (*func)() = dlsym(handle, "test_func");
    printf("dlsym  return %p\n", func);

    if (func) (*func)();
    return 0;
}

编译后运行失败,输出:

$ ./a.out
dlopen return 0xe29dfbec1c7bc0d
dlsym  return 0x0

但通过readelf能看到该符号存在:

$ readelf -s a.out | grep test_func
    40: 00000000000017c8    36 FUNC    GLOBAL DEFAULT   13 test_func

问题原因与解决方法

核心问题

readelf查看的是静态符号表,而dlsym查找的是动态符号表。GCC默认编译可执行文件时,不会将全局符号加入动态符号表,因此即使符号存在,动态链接器也无法找到。

解决方式一:添加编译选项-rdynamic

编译时加上-rdynamic选项,它会将所有全局符号导出到动态符号表中,让dlsym可以找到目标函数:

gcc test.c -o a.out -ldl -rdynamic

解决方式二:显式设置函数可见性

修改test_func的定义,添加visibility("default")属性,单独将该符号导出到动态符号表,无需全局导出所有符号:

#include <stdio.h>
#include <dlfcn.h>

void __attribute__((visibility("default"))) test_func(void)
{
    printf("test_func in %s\n",__FILE__);
}

int main()
{
    void *handle = dlopen(0, RTLD_LAZY);
    printf("dlopen return %p\n", handle);

    void (*func)() = dlsym(handle, "test_func");
    printf("dlsym  return %p\n", func);

    if (func) (*func)();
    return 0;
}

编译时只需链接动态链接库:

gcc test.c -o a.out -ldl

验证效果

两种方式编译后运行,都会输出:

dlopen return 0xXXXXXX
dlsym  return 0xXXXXXX
test_func in test.c

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 20:12:32