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

aarch64平台C++调用libmongoose C共享库值传参段错误咨询

aarch64架构下C++调用C共享库值传参触发段错误排查

故障背景

  • 运行环境:aarch64(arm64)架构
  • 业务构成:基于C++11开发的应用,依赖C语言实现的共享库libmongoose
  • C++侧调用代码如下:
void some_class::some_function_in_CPP_application()
{
    // 局部mg_connect_opts对象
    struct mg_connect_opts opts;

    // 给opts成员赋值
    opts.error_string = &err_str;
    opts.user_data = this;

    // 按值传递opts参数
    struct mg_connection *nc = mg_connect_ws_opt(mgr, ev_handler, opts, uri, nullptr, nullptr);
}
  • C共享库侧mg_connect_ws_opt函数签名如下:
struct mg_connection *mg_connect_ws_opt(
    struct mg_mgr *mgr, MG_CB(mg_event_handler_t ev_handler, void *user_data),
    struct mg_connect_opts opts, const char *url, const char *protocol,
    const char *extra_headers);

异常现象

按照函数签名定义,opts为值传递参数,理论上参数拷贝过程不会触发内存访问问题,但分析core dump调用栈时出现异常:

  1. C++代码侧,调用mg_connect_ws_opt前,gdb打印opts对象内容完全正常:
(gdb) print opts
$5 = {
  user_data = 0x7fe8e70f40, 
  flags = 0, 
  error_string = 0x5569ba17b8 <err_str>, 
  iface = 0x0, 
  nameserver = 0x0, 
  ssl_cert = 0x0, 
  ssl_key = 0x0, 
  ssl_ca_cert = 0x0, 
  ssl_cipher_suites = 0x556965e850 "PSKADJSAFSAK", 
  ssl_server_name = 0x0, 
  ssl_psk_identity = 0x55a07451a0 "21321521321321312312321", 
  ssl_psk_key = 0x55a0742e20 "43124321rsafsa32131zcxbsa"
}
  1. 切换到调用栈下一帧(C库内mg_connect_ws_opt函数帧)时,opts参数无法访问:
(gdb) frame 4
#4  0x0000007fb59fdfd4 in mg_connect_ws_opt (mgr=<optimized out>, 
    ev_handler=<optimized out>, 
    opts=<error reading variable: Cannot access memory at address 0xffffffffffffffff>, url=<optimized out>, protocol=0x0, extra_headers=0x0)
(gdb) print opts
Cannot access memory at address 0xffffffffffffffff

问题解答与排查思路

核心结论

该故障不是C/C++调用约定差异直接导致,给调用方函数加extern "C"无法解决问题。
aarch64遵循AAPCS64调用规范:当值传递的结构体尺寸超过通用寄存器承载上限时,调用方会在自身栈帧上分配结构体副本,将副本指针传递给被调用函数。你看到的0xffffffffffffffff非法地址,本质是被调用方读取opts成员时,拿到了错误偏移位置的垃圾值,根因90%以上是C++侧和C共享库侧看到的struct mg_connect_opts内存布局不一致。
extern "C"仅作用于函数符号的名称修饰规则,不影响结构体的内存布局,你当前已经能正常进入mg_connect_ws_opt函数帧,说明符号解析完全正常,不需要给调用方加该修饰。

排查优先级

  1. 优先核对两边使用的头文件一致性
    检查C++代码包含的mongoose.h,和编译libmongoose时使用的mongoose.h是否为完全相同的版本,重点核对:
    • struct mg_connect_opts的成员顺序、成员数量是否一致
    • 结构体中是否存在条件编译包裹的成员(比如#ifdef MG_ENABLE_SSL控制的SSL相关字段),两边编译时的宏定义是否匹配

    你打印的opts中存在ssl_cipher_suites、ssl_psk_identity等SSL相关字段,非常大概率是编译C++代码时开启了SSL相关宏,但编译libmongoose时关闭了对应宏,或者反过来,导致两边结构体中SSL字段的偏移完全错位,值传递时拷贝的内存长度不匹配,被调用方读成员时直接访问非法地址。

  2. 直接校验结构体尺寸
    分别在C++调用侧、C库函数内打印sizeof(struct mg_connect_opts)的值,如果两个值不相等,可直接坐实头文件/宏定义不匹配的问题。
  3. 排查结构体对齐规则
    如果确认头文件、宏定义完全一致,检查C++代码中是否存在#pragma pack等修改结构体默认对齐的指令,或者编译时加了自定义对齐参数,导致两边结构体对齐规则不一致、成员偏移错位。

临时验证方案

如果暂时无法重新编译libmongoose,可以临时将mg_connect_ws_opt的opts参数改为指针传递,修改后如果参数访问恢复正常,即可确认是值传递时两边结构体大小不一致导致的拷贝长度错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 15:21:17