localtime_r在程序退出前消耗一些内存 [英] localtime_r consuming some memory before program exit

查看:1241
本文介绍了localtime_r在程序退出前消耗一些内存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用valgrind的massif在程序退出
之前的最后阶段跟踪内存使用,并找到

I use valgrind's massif to track memory usage at the last stage before program exit and found


  • js :: DateTimeInfo :: updateTimeZoneAdjustment()(DateTime.cpp:19)

这是调用localtime_r并消耗一些内存。

which is calling localtime_r and consuming some memory.

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的massif

ms_print of last snapshot from valgrind's massif

427711 --------------------------------------------------------------------------------
427712   n        time(i)         total(B)   useful-heap(B) extra-heap(B)    stacks(B)
427713 --------------------------------------------------------------------------------
427714  95 15,049,552,789              256              165            91            0
427715 64.45% (165B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc.
427716 ->36.72% (94B) 0x37AFA9EA6A: __tzfile_read (in /lib64/libc-2.12.so)
427717 | ->36.72% (94B) 0x37AFA9DC02: tzset_internal (in /lib64/libc-2.12.so)
427718 |   ->36.72% (94B) 0x37AFA9DD67: __tz_convert (in /lib64/libc-2.12.so)
427719 |     ->36.72% (94B) 0x4CAE552: js::DateTimeInfo::updateTimeZoneAdjustment() (DateTime.cpp:19)
427720 |       ->36.72% (94B) 0x4D814C9: JSRuntime::JSRuntime(JSUseHelperThreads) (jsapi.cpp:856)
427721 |         ->36.72% (94B) 0x4D8B71A: JS_NewRuntime(unsigned int, JSUseHelperThreads) (Utility.h:491)
427722 |           ->36.72% (94B) 0x40162A: main (js.cc:58)
427723 |
427724 ->15.62% (40B) 0x37AFA9D0D0: __tzstring (in /lib64/libc-2.12.so)
427725 | ->15.62% (40B) 0x37AFA9EF99: __tzfile_read (in /lib64/libc-2.12.so)
427726 |   ->15.62% (40B) 0x37AFA9DC02: tzset_internal (in /lib64/libc-2.12.so)
427727 |     ->15.62% (40B) 0x37AFA9DD67: __tz_convert (in /lib64/libc-2.12.so)
427728 |       ->15.62% (40B) 0x4CAE552: js::DateTimeInfo::updateTimeZoneAdjustment() (DateTime.cpp:19)
427729 |         ->15.62% (40B) 0x4D814C9: JSRuntime::JSRuntime(JSUseHelperThreads) (jsapi.cpp:856)
427730 |           ->15.62% (40B) 0x4D8B71A: JS_NewRuntime(unsigned int, JSUseHelperThreads) (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_internal (in /lib64/libc-2.12.so)
427735 |   ->05.86% (15B) 0x37AFA9DD67: __tz_convert (in /lib64/libc-2.12.so)
427736 |     ->05.86% (15B) 0x4CAE552: js::DateTimeInfo::updateTimeZoneAdjustment() (DateTime.cpp:19)
427737 |       ->05.86% (15B) 0x4D814C9: JSRuntime::JSRuntime(JSUseHelperThreads) (jsapi.cpp:856)
427738 |         ->05.86% (15B) 0x4D8B71A: JS_NewRuntime(unsigned int, JSUseHelperThreads) (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_NewRuntime(unsigned int, JSUseHelperThreads) (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_NewRuntime(unsigned int, JSUseHelperThreads) (jsapi.cpp:1121)
427753 |   ->00.00% (0B) 0x40162A: main (js.cc:58)

在我的程序退出之前释放这个? (从我的理解,它会清除程序退出时)

Is there anyway to free this before my program exit ? ( from my understanding it will be cleared when program exit )

推荐答案

为什么 localtime_r code>分配内存?



C运行库中的日期/时间函数需要知道关于时区的各种信息,例如夏令时夏令时开始和结束这些文件存储在所谓的时区文件中。

第一次调用某些相关的日期/时间函数时,需要加载,解析该文件并将其数据存储在某处,以便对这些函数的进一步调用不会再次引起相同的惩罚。

The first time some related date/time function is called, this file needs to be loaded, parsed and its data stored somewhere, so that further calls to these functions do not incur the same penalty again. The allocations you see are related to that.

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

This memory is allocated, but never freed during the execution of the program, and therefore can be considered a memory leak. But really it is not a bug, because it is a conscious decision by the library authors.

如上所述,数据被加载一次,并且从那以后对于程序的其余运行时。他们将只在最后,在过程终止之前被释放。实际上有很多结构在libc中具有相同的使用模式。

As I wrote above, the data are loaded once and are (possibly) used ever since for the rest of the runtime of the program. They would be released only at the very end, before the process terminates. There is actually many structures with the same usage pattern in libc.

所以他们认为,不是一个一个地遍历所有的分配,释放内存,它在那里,因为在下一毫秒,进程将结束反正,内核将收回所有分配的内存反正(和更快,而在它,整个堆一次)。

So they thought that instead of going through all the allocations one by one, freeing the memory, they just leave it there, because in the next millisecond the process will end anyway and the kernel will reclaim all allocated memory back anyway (and much faster, while at it, the whole heap at once).

不是真的,有!但不适合临时用户...由于 Valgrind文档说明:

Not really, there is! But not for a casual user... As Valgrind documentation states:


glibc作者意识到,当在exit处进行泄漏检查时,这种行为会导致泄漏检查器(例如Valgrind)错误地报告glibc中的泄漏。为了避免这种情况,他们提供了一个叫做 __ libc_freeres 的程序,使glibc释放所有已分配的内存。

The glibc authors realised that this behaviour causes leak checkers, such as Valgrind, to falsely report leaks in glibc, when a leak check is done at exit. In order to avoid this, they provided a routine called __libc_freeres specifically to make glibc release all memory it has allocated.

正如所料,处理时区文件的例程确实使用这种freeres机制,例如 time / tzfile。 c

As expected, the routines dealing with timezone file are indeed using this "freeres" mechanism, e.g. time/tzfile.c:

libc_freeres_ptr (static time_t *transitions);

Valgrind在结束之前调用此例程,因此如果使用(默认)工具memcheck运行它,你看不到任何这些泄漏。即使对于您的程序,它们也应该消失,它可能只是 massif ,其中列出了分配,当它们发生,而不是一切都完成后。

Valgrind calls this routine before end, so that if you run it with the (default) tool memcheck, you don't see any of these "leaks". They should disappear even for your program, it's probably just massif which lists the allocations when they happen and not after everything has finished.

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

You might have success calling __libc_freeres yourself, but it might also just crash, because libc still does some internal processing after the end of user's main() function and you might release its internal structures prematurely.

这篇关于localtime_r在程序退出前消耗一些内存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆