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

aarch64平台vsnprintf返回-1原因及core dump下GDB排查方法

问题背景

应用运行于aarch64(arm64)架构时出现段错误,观测到vsnprintf持续调用失败、返回值为-1,目前已确认段错误由第三方库的异常逻辑引发,待确认三个问题:

  • vsnprintf调用失败的全部可能原因
  • 无存活运行进程、仅持有core dump文件时,是否可通过GDB读取errno定位vsnprintf失败原因
  • 代码中传入的异常长度参数是否为vsnprintf调用失败的诱因

问题涉及的代码实现如下:

int mg_printf(const char *fmt, ...) {
  int len;
  char mem[100];
  va_list ap;
  va_start(ap, fmt);
  len = vsnprintf(mem, sizeof(mem), fmt, ap); // 此处持续调用失败
  va_end(ap);
  return len;
}

// len值异常
int len = 1602988490;
const char* pr = "[aaaa:bbbb:0000:0000:0000:0000:0000:0010]:12345";
mg_printf("Host: %.*s\r\n", len, pr);
问题解答

异常len参数是否是vsnprintf失败的直接诱因

是,这个异常值就是你当前场景下vsnprintf返回-1的核心原因。
%.*s格式符的语义是:从传入的字符指针起始位置开始,最多读取「精度值」个字节的字符,遇到\0提前终止。你传入的精度值为1602988490,远大于pr指向的字符串实际长度(算上IPv6地址和端口一共也就40余字节)。vsnprintf处理该格式符时,会尝试从pr指针地址开始向后读取最高1.6GB左右的内存,这个范围远超过字符串本身所在的合法内存段,几乎必然触碰到未映射的内存页,触发内存访问错误,直接导致函数返回-1。
这里要注意:正常情况下vsnprintf遇到待输出内容长度超过传入的缓冲区大小时不会报错,只会返回内容的完整预期长度,不会返回-1。只有触发非法访问、格式错误、溢出类问题时才会返回-1。

vsnprintf调用失败的全部可能原因

  • 传入的格式串指针fmt为非法值,指向不可读内存
  • 可变参数列表和格式串要求的参数类型、数量不匹配,比如%.*s要求传入int类型精度、char*类型字符串指针,若传入的精度值过大、字符串指针为非法值,会导致读取非法内存
  • 读取待格式化的源数据时触达不可读内存页,触发内存访问错误,此时errno会被设置为EFAULT
  • 格式串中包含非法的多字节字符序列,编码校验失败,此时errno会被设置为EILSEQ
  • 传入的输出缓冲区指针为非法值,指向不可写内存(你当前代码里mem是栈上分配的100字节数组,属于合法地址,可排除该原因)
  • 部分libc实现中,若待格式化生成的字符串总长度超过INT_MAX,会返回-1,此时errno会被设置为EOVERFLOW

core dump场景下能否通过GDB查看errno定位失败原因

只要core文件生成时相关内存没有被破坏,就可以查看,注意几个细节:

  • aarch64架构下errno是线程局部存储变量,GDB加载core文件后,切换到触发vsnprintf失败的对应线程,直接执行p errno就能读取到线程当时的errno值,再执行p strerror(errno)就能拿到对应的错误描述。
  • 两种场景下读到的errno值没有参考价值:
    • vsnprintf返回-1之后,当前线程又执行了其他会修改errno的系统调用或库函数,core中存储的errno值会被后续逻辑覆盖,无法反映vsnprintf失败时的真实错误
    • 内存越界写、栈溢出等问题破坏了线程局部存储中errno所在的内存区域,读出来的值是随机垃圾值
  • 针对你当前的场景,不需要依赖errno也能直接定位问题:在GDB中切到mg_printf的栈帧,直接读取可变参数列表中对应的len值、pr指针值,再用x/s pr查看pr指向的实际字符串长度,就能直接验证是否是超大精度值触发的越界读问题。

内容的提问来源于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:48:17