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

显式调用C++动态库random.so触发SIGSEGV错误求助

问题原因与解决方案

问题原因分析

  1. 命令行参数缺失:运行./example时未传入函数名参数,argv[1]为空指针,导致dlsym尝试查找空字符串对应的符号,必然失败,rand指针未被正确初始化,调用时触发段错误。
  2. C++名字修饰问题:C++编译器会对函数名进行名字修饰(Name Mangling),动态库中的rand_int实际符号名并非原始的rand_int,而是经过编译器编码后的字符串,直接用dlsym查找rand_int会找不到目标符号,rand成为无效指针。
  3. 未检查dlsym返回值:即使传入参数,代码也没有验证dlsym是否成功获取符号,一旦查找失败,调用无效指针会直接触发段错误。

解决方案

1. 修复命令行参数问题

运行程序时必须传入目标函数名参数,例如:

./example rand_int

同时在代码中增加参数合法性检查,避免空指针访问:

if (argc < 2) {
    fprintf(stderr, "Usage: %s <function_name>\n", argv[0]);
    return 1;
}

2. 解决C++名字修饰问题

推荐采用以下两种方式之一:

  • 方式一:用extern "C"导出函数
    修改头文件和库代码,让函数以C语言的规则导出,避免名字修饰:
// random.h
#ifdef __cplusplus
extern "C" {
#endif
int rand_int(int min, int max);
#ifdef __cplusplus
}
#endif
// random.cpp
#include <random>
extern "C" {
int rand_int(int min, int max) {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<int> dist(min, max);
    return dist(gen);
}
}

重新编译动态库后,rand_int会以原始名字存在于库中,dlsym可以直接找到。

  • 方式二:使用修饰后的符号名(不推荐)
    先通过nm命令查看库中实际的符号名:
nm -D /home/nikita/Libraries/shared/librandom.so | grep rand_int

输出会是类似_Z8rand_intii的修饰名,运行程序时传入该名字即可:

./example _Z8rand_intii

该方式移植性差,不同编译器的修饰规则可能不同,仅作临时调试使用。

3. 增加dlsym错误检查

在调用dlsym后必须检查是否成功获取符号:

rand = (int (*)(int, int))dlsym(ext_library, argv[1]);
char *err = dlerror();
if (err != nullptr) {
    fprintf(stderr, "dlsym() error: %s\n", err);
    dlclose(ext_library);
    return 1;
}

4. 完整修复后的example.cpp代码

#include <cstdio>
#include <dlfcn.h>

int main(int argc, char *argv[]) {
    void *ext_library;
    int (*rand)(int, int);

    // 检查命令行参数
    if (argc < 2) {
        fprintf(stderr, "Usage: %s <function_name>\n", argv[0]);
        return 1;
    }

    ext_library = dlopen("/home/nikita/Libraries/shared/librandom.so", RTLD_LAZY);
    if (!ext_library) {
        fprintf(stderr, "dlopen() error: %s\n", dlerror());
        return 1;
    }

    // 获取函数符号并检查错误
    rand = (int (*)(int, int))dlsym(ext_library, argv[1]);
    char *err = dlerror();
    if (err != nullptr) {
        fprintf(stderr, "dlsym() error: %s\n", err);
        dlclose(ext_library);
        return 1;
    }

    printf("%d\n", (*rand)(0, 10));

    dlclose(ext_library);
    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 12:25:02