C++程序调用mktime()持续分配堆内存占用增长问题求助
问题原因
- 你遇到的是glibc老版本(对应你Raspbian 10/Buster系统搭载的glibc 2.28版本)的已知问题:mktime内部处理时区信息时,若未提前初始化时区数据、或传入的
struct tm未完整初始化,会反复分配小体积的时区缓存块,这些块被挂在libc全局结构体上,valgrind会标记为still reachable不算直接泄漏,但长时间运行会持续占用内存。 - 你的代码还有两个触发问题的诱因:1. 全局
struct tm result没有每次使用前完整初始化,仅赋值了年月日时分秒字段,tm_isdst(夏令时标记)等字段的值不确定,会强制mktime每次调用都重新查询时区信息;2. 没有提前初始化时区,mktime每次调用都会尝试加载时区数据产生额外分配。
解决方案
方案1:快速修复(修改现有代码,无需换实现)
- 程序启动时调用一次
tzset()完成全局时区初始化,避免mktime重复加载时区。 - 每次使用
struct tm前完整初始化所有字段,尤其显式指定tm_isdst的值:如果不需要处理夏令时可以直接设为0,设为-1则让mktime自动判断。可以把全局result改成函数局部变量,每次定义时清零,避免残留值干扰。
修改后的tmConvert_t参考代码:
unsigned long long tmConvert_t(int YY, short MM, short DD, short hh, short mm, short ss) { struct tm result = {0}; // 局部变量,每次初始化全0 result.tm_sec = ss; result.tm_min = mm; result.tm_hour = hh; result.tm_year = YY - 1900; result.tm_mon = MM; result.tm_mday = DD; result.tm_isdst = -1; // 显式指定夏令时标记由mktime自动判断 time_t converted = mktime(&result); return (unsigned long long)converted * 1000; }
程序入口加初始化逻辑:
#include <time.h> // main函数最开始调用一次 tzset();
方案2:彻底规避(用C++ chrono接口替代libc时间函数)
既然你已经用了C++11及以上的std::chrono,完全可以不用libc的mktime/localtime系列函数,直接用chrono计算当天午夜时间戳,彻底避开libc的实现问题:
#include <chrono> using namespace std::chrono; void updateTime() { auto now = system_clock::now(); currentMillisTime = duration_cast<milliseconds>(now.time_since_epoch()).count(); // 直接用chrono算当天午夜,不需要调用mktime auto dayPoint = floor<days>(now); midnightMillis = duration_cast<milliseconds>(dayPoint.time_since_epoch()).count(); // 获取年月日周日信息 time_t t = system_clock::to_time_t(now); struct tm result; localtime_r(&t, &result); currentDay = result.tm_mday; currentMonth = result.tm_mon; currentYear = result.tm_year + 1900; currentWeekday = result.tm_wday; }
该方案完全不会触发libc的mktime分配问题,长期运行更稳定。
内容的提问来源于stack exchange,提问作者tryingHard
相关产品推荐
相关产品推荐

