ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【segmentation fault】vsnprintf错误用法

2022-06-17 21:03:58  阅读:209  来源: 互联网

标签:vsnprintf segmentation fault len ap logger bufsize buf size


最近运气欠佳,又遇到服务崩溃问题
重构服务在长时间压测场景下会出现崩溃,但是崩溃的地方根本没有任何问题,又是最恶心的A函数内存越界影响B函数问题。
先给出问题代码

char* buf = logger->buf;
int bufsize = logger->bufsize;
int len = snprintf(buf, bufsize, "%s[%04d-%02d-%02d %02d:%02d:%02d.%03d][%s] ",
    pcolor,
    year, month, day, hour, min, sec, ms, plevel);

va_list ap;
va_start(ap, fmt);
len += vsnprintf(buf + len, bufsize - len, fmt, ap);
va_end(ap);

if (logger->enable_color) {
    len += snprintf(buf + len, bufsize - len, "%s", CLR_CLR);
}

if (logger->handler) {
    logger->handler(level, buf, len);
}
else {
    FILE* fp = shift_logfile(logger);
    if (fp) {
        fwrite(buf, 1, len, fp);
        if (logger->enable_fsync) {
            fflush(fp);
        }
    }
}
int vsnprintf(char* str, size_t size, const char* format, va_list ap);

函数简介
将可变参数格式化输出到一个字符数组。
 
参数说明
str: 指向存储结果C字符串的缓冲区的指针。
size:  str可接受的最大字符数
format: 指定输出格式的字符串
ap: va_list变量

返回值
执行成功,返回最终生成字符串的长度,若生成字符串的长度大于size,则将字符串的前size个字符复制到str,同时将原串的长度返回(不包含终止符);
执行失败,返回负值,更新errno.

问题出现在 vsnprintf 函数上,最容易出问题的是"若生成字符串的长度大于size,则将字符串的前size个字符复制到str,同时将原串的长度返" 即返回值可能大于size, len += vsnprintf(buf + len, bufsize - len, fmt, ap); 假设 len > bufsize,snprintf(buf + len, bufsize - len, "%s", CLR_CLR);就会产生内存越界。

问题解决流程

  1. 测试发现崩溃问题;
  2. 去除jemalloc库,再次测试,分析堆栈日志,崩溃的在内核组,请内核组协助;
  3. 内核组反馈内核代码没有问题;
  4. 光凭backtrace无法分析出问题,关闭信号抓取函数,准备获取coredump文件分析,测试反馈问题消失;
  5. 通过排除法发现设置 ulimit -l 134217728 可以规避问题,但是我不认为这是根本原因;
  6. 还是基于排除法解决问题,31版本是没有问题的。基于31版本比较两个版本的修改,采取排除法打版本测试;
  7. 发现添加打印日志方法之后问题出现;
  8. 怀疑是日志过大,导致内存越界,分析日志源码,发现以上问题;
  9. 修改之后再次测试,测试正常。

标签:vsnprintf,segmentation,fault,len,ap,logger,bufsize,buf,size
来源: https://www.cnblogs.com/zhanggaofeng/p/16387023.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有