localtime_r потребляет немного памяти перед выходом из программы

Я использую массив valgrind для отслеживания использования памяти на последнем этапе перед выходом из программы
и нашел

  • 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)

ms_print последнего снимка из массива Вальгринда

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)

Есть ли способ освободить это до выхода из моей программы? (из моего понимания это будет очищено при выходе из программы)

2

Решение

Почему localtime_r() выделить память?

Функции даты / времени в библиотеке времени выполнения C должны знать различную информацию о часовых поясах, например, когда начинается и заканчивается летнее летнее время и т. Д. Они хранятся в так называемых Файл часового пояса.

При первом вызове некоторой связанной функции даты / времени этот файл должен быть загружен, проанализирован и его данные где-то сохранены, так что дальнейшие вызовы этих функций не повлекут за собой то же наказание. Распределения, которые вы видите, связаны с этим.

Так это утечка памяти?

Эта память выделяется, но никогда не освобождается во время выполнения программы, и, следовательно, может рассматриваться как утечка памяти. Но на самом деле это не ошибка, потому что это сознательное решение авторов библиотеки.

Как я писал выше, данные загружаются один раз и (возможно) используются с тех пор для остальной части времени выполнения программы. Они будут выпущены только в самом конце, до завершения процесса. На самом деле в libc много структур с одинаковым шаблоном использования.

Поэтому они подумали, что вместо того, чтобы проходить все выделения один за другим, освобождая память, они просто оставляют ее там, потому что в течение следующей миллисекунды процесс все равно завершится, и ядро ​​все равно вернет всю выделенную память (и гораздо быстрее, пока у него целая куча сразу).

Значит нет способа избавиться от этого?

Не совсем, есть! Но не для обычного пользователя … Как Valgrind документация состояния:

Авторы glibc поняли, что такое поведение приводит к тому, что средства проверки утечки, такие как Valgrind, ложно сообщают об утечках в glibc, когда проверка утечки выполняется на выходе. Чтобы избежать этого, они предоставили процедуру, называемую __libc_freeres специально для того, чтобы glibc освободил всю выделенную память.

Как и ожидалось, подпрограммы, имеющие дело с файлом часового пояса, действительно используют этот механизм «freeres», например, time/tzfile.c:

libc_freeres_ptr (static time_t *transitions);

Valgrind вызывает эту процедуру до конца, поэтому, если вы запустите ее с помощью (по умолчанию) инструмента memcheck, вы не увидите ни одной из этих «утечек». Они должны исчезнуть даже для вашей программы, это, вероятно, просто массив в котором перечислены распределения, когда они происходят, а не после того, как все закончилось.

Вы могли бы успешно звонить __libc_freeres самостоятельно, но это также может привести к сбою, потому что libc все еще выполняет некоторую внутреннюю обработку после окончания работы пользователя. main() функционировать, и вы могли бы преждевременно освободить его внутренние структуры.

1

Другие решения


По вопросам рекламы [email protected]