【segmentation fault】vsnprintf错误用法
2022/6/17 23:28:18
本文主要是介绍【segmentation fault】vsnprintf错误用法,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
最近运气欠佳,又遇到服务崩溃问题
重构服务在长时间压测场景下会出现崩溃,但是崩溃的地方根本没有任何问题,又是最恶心的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);就会产生内存越界。
问题解决流程
- 测试发现崩溃问题;
- 去除jemalloc库,再次测试,分析堆栈日志,崩溃的在内核组,请内核组协助;
- 内核组反馈内核代码没有问题;
- 光凭backtrace无法分析出问题,关闭信号抓取函数,准备获取coredump文件分析,测试反馈问题消失;
- 通过排除法发现设置 ulimit -l 134217728 可以规避问题,但是我不认为这是根本原因;
- 还是基于排除法解决问题,31版本是没有问题的。基于31版本比较两个版本的修改,采取排除法打版本测试;
- 发现添加打印日志方法之后问题出现;
- 怀疑是日志过大,导致内存越界,分析日志源码,发现以上问题;
- 修改之后再次测试,测试正常。
这篇关于【segmentation fault】vsnprintf错误用法的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-24Java中定时任务实现方式及源码剖析
- 2024-11-24Java中定时任务实现方式及源码剖析
- 2024-11-24鸿蒙原生开发手记:03-元服务开发全流程(开发元服务,只需要看这一篇文章)
- 2024-11-24细说敏捷:敏捷四会之每日站会
- 2024-11-23Springboot应用的多环境打包入门
- 2024-11-23Springboot应用的生产发布入门教程
- 2024-11-23Python编程入门指南
- 2024-11-23Java创业入门:从零开始的编程之旅
- 2024-11-23Java创业入门:新手必读的Java编程与创业指南
- 2024-11-23Java对接阿里云智能语音服务入门详解