C++ localtime\r在程序退出前消耗一些内存

C++ localtime\r在程序退出前消耗一些内存,c++,memory-leaks,valgrind,localtime,massif,C++,Memory Leaks,Valgrind,Localtime,Massif,我使用valgrind的massif来跟踪程序退出前最后阶段的内存使用情况 发现 js::DateTimeInfo::updateTimeZoneAdjustment()(DateTime.cpp:19) 调用localtime\r并消耗一些内存 16 ComputeLocalTime(time_t local, struct tm *ptm) 17 { 18 #ifdef HAVE_LOCALTIME_R 19 return localtime_r(&local, ptm)

我使用valgrind的massif来跟踪程序退出前最后阶段的内存使用情况 发现

  • js::DateTimeInfo::updateTimeZoneAdjustment()(DateTime.cpp:19)
调用localtime\r并消耗一些内存

16 ComputeLocalTime(time_t local, struct tm *ptm)
17 {
18 #ifdef HAVE_LOCALTIME_R
19     return localtime_r(&local, ptm);
20 #else
21     struct tm *otm = localtime(&local);
22     if (!otm)
valgrind地块最后一张快照的ms_打印

427711--------------------------------------------------------------------------------
427712 n时间(i)总计(B)有用堆(B)额外堆(B)堆栈(B)
427713 --------------------------------------------------------------------------------
427714  95 15,049,552,789              256              165            91            0
427715 64.45%(165B)(堆分配函数)malloc/new/new[],--alloc fns等。
427716->36.72%(94B)0x37AFA9EA6A:uuuTZfile_Uread(in/lib64/libc-2.12.so)
427717 |->36.72%(94B)0x37AFA9DC02:tzset|U内部(in/lib64/libc-2.12.so)
427718 |->36.72%(94B)0x37AFA9DD67:|转换(in/lib64/libc-2.12.so)
427719 |->36.72%(94B)0x4CAE552:js::DateTimeInfo::updateTimeZoneAdjustment()(DateTime.cpp:19)
427720 |->36.72%(94B)0x4D814C9:JSRuntime::JSRuntime(jsuseheloperthreads)(jsapi.cpp:856)
427721 |->36.72%(94B)0x4D8B71A:JS_NewRuntime(unsigned int,jsuseheloperthreads)(Utility.h:491)
427722 |->36.72%(94B)0x40162A:main(js.cc:58)
427723 |
427724->15.62%(40B)0x37AFA9D0D0:uu tzstring(in/lib64/libc-2.12.so)
427725 |->15.62%(40B)0x37AFA9EF99:| tzfile|u读取(in/lib64/libc-2.12.so)
427726 |->15.62%(40B)0x37AFA9DC02:tzset|U内部(in/lib64/libc-2.12.so)
427727 |->15.62%(40B)0x37AFA9DD67:|转换(in/lib64/libc-2.12.so)
427728 |->15.62%(40B)0x4CAE552:js::DateTimeInfo::updateTimeZoneAdjustment()(DateTime.cpp:19)
427729 |->15.62%(40B)0x4D814C9:JSRuntime::JSRuntime(jsuseheloperthreads)(jsapi.cpp:856)
427730 |->15.62%(40B)0x4D8B71A:JS_NewRuntime(unsigned int,jsuseheloperthreads)(Utility.h:491)
427731 |->15.62%(40B)0x40162A:main(js.cc:58)
427732 |
427733->05.86%(15B)0x37AFA81170:strdup(in/lib64/libc-2.12.so)
427734 |->05.86%(15B)0x37AFA9DBEF:tzset_内部(in/lib64/libc-2.12.so)
427735 |->05.86%(15B)0x37AFA9DD67:|转换(in/lib64/libc-2.12.so)
427736 |->05.86%(15B)0x4CAE552:js::DateTimeInfo::updateTimeZoneAdjustment()(DateTime.cpp:19)
427737 |->05.86%(15B)0x4D814C9:JSRuntime::JSRuntime(jsuseheloperthreads)(jsapi.cpp:856)
427738 |->05.86%(15B)0x4D8B71A:JS_NewRuntime(unsigned int,jsuseheloperthreads)(Utility.h:491)
427739 |->05.86%(15B)0x40162A:main(js.cc:58)
427740 |
427741->03.12%(8B)0x4015C6:allocate()(js.cc:41)
427742 |->03.12%(8B)0x40187E:main(js.cc:114)
427743 |
427744->03.12%(8B)0x4015E2:allocate()(js.cc:43)
427745 |->03.12%(8B)0x40187E:main(js.cc:114)
427746 |
427747->00.00%(0B)0x4D8B3E8:JSRuntime::init(unsigned int)(Utility.h:154)
427748 |->00.00%(0B)0x4D8B73B:JS_新运行时(unsigned int,jsuseheloperthreads)(jsapi.cpp:1121)
427749 |->00.00%(0B)0x40162A:main(js.cc:58)
427750 |
427751->00.00%(0B)0x4D8B435:JSRuntime::init(unsigned int)(Utility.h:154)
427752 |->00.00%(0B)0x4D8B73B:JS_新运行时(unsigned int,jsuseheloperthreads)(jsapi.cpp:1121)
427753 |->00.00%(0B)0x40162A:main(js.cc:58)
在我的程序退出之前,是否有任何方法可以释放此文件?(据我所知,当程序退出时它将被清除)

为什么
localtime\u r()
分配内存? C运行时库中的日期/时间函数需要知道关于时区的各种信息,如夏季夏令时何时开始和结束等。这些信息存储在所谓的

第一次调用某个相关的日期/时间函数时,需要加载、解析该文件并将其数据存储在某个位置,以便对这些函数的进一步调用不会再次招致相同的惩罚。您看到的分配与此相关

那么这是内存泄漏吗? 该内存已分配,但在程序执行期间从未释放,因此可被视为内存泄漏。但实际上这不是一个bug,因为这是图书馆作者有意识的决定

正如我在上面所写的,数据只加载一次,并且(可能)在程序的其余运行时使用。它们只会在进程结束之前的最后一刻发布。实际上,libc中有许多具有相同使用模式的结构

因此,他们认为,与其一个接一个地进行所有分配,释放内存,不如将其留在那里,因为在接下来的毫秒内,进程无论如何都会结束,内核无论如何都会回收所有分配的内存(而且速度更快,同时一次回收整个堆)

所以没有办法摆脱这个? 不是真的,有!但不是为一个随意的用户。。。如各国所述:

glibc的作者意识到,当在出口处进行泄漏检查时,这种行为会导致泄漏检查人员(如Valgrind)在glibc中错误报告泄漏。为了避免这种情况,他们提供了一个名为
\uu libc\u freeres
的例程,专门让glibc释放它分配的所有内存

正如预期的那样,处理时区文件的例程确实使用了这种“freeres”机制,例如:

Valgrind在结束之前调用这个例程,所以如果您使用(默认)工具memcheck运行它,您不会看到任何这些“泄漏”。即使对于您的程序,它们也应该消失,可能只是massif在分配发生时列出了分配,而不是在所有事情都完成之后


您自己调用
\u libc\u freeres可能会成功,但它也可能会崩溃,因为libc在用户的
main()
函数结束后仍会进行一些内部处理,您可能会过早地释放其内部结构。

我快速查看了
\u tzfile\u read
libc_freeres_ptr (static time_t *transitions);