microsoft / microsoft/STL

<chrono>: Possible way forward to avoid `tzdb`'s memory leak

Open
#2,504 4 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

bug chrono
Dominant language
C++
Stars
11.1k
Forks
1.7k
Avg merge
4d 15h
Merged PRs (30d)
22

Description

[ Copied over from DevCom-1644641 ]

[severity:It’s more difficult to complete my work]

This bug has already been reported at https://developercommunity2.visualstudio.com/t/std::chrono::current_zone-produces-a/1513362 before, but that issue got closed.

Repro Program: chronoleak.cpp:

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>

#include <chrono>

int main() {
        _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
        _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
        _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
        _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
        _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
        _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
        _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
        {
                std::chrono::get_tzdb_list();
        }
        return 0;
}

Compile command: cl /std:c++20 /permissive- /EHsc /MTd chronoleak.cpp

Output see attached leaks.txt (memory leaks reported)

I disagree with the comment in https://developercommunity2.visualstudio.com/t/std::chrono::current_zone-produces-a/1513362#T-N1516296.

I think wrapping inline atomic<tzdb_list*> _Global_tzdb_list; (see https://github.com/microsoft/STL/blob/59a87ccc947ed4ccefd3b87e51b6a7136341c674/stl/inc/chrono#L2852>) in a struct that has a destructor could run the required cleanup. If destruction order on process shutdown is a concern, I think the standard allows throwing if it would be called after the containing object had already been destroyed. See C++20 [time.zone.db.access]:

Throws: runtime_error if for any reason a reference cannot be returned to a valid tzdb_list containing one or more valid tzdbs.

This memory leak blocks adoption of C++20 std::chrono functionality in OpenMPT and libopenmpt (https://github.com/OpenMPT/openmpt/) because the resulting noise makes using the CRT memory leak detector impractical for us. In our case, tzdb is loaded via a call to std::chrono::from_stream() as in:

std::chrono::utc_clock::time_point tp{};
std::istringstream s;
s.imbue(std::locale::classic());
s.str("2022-01-01 23:42");
std::chrono::from_stream(s, "%F %R", tp);

Related Context

  • #2047
  • DevCom-1513362

Further ABI Considerations

As noted in #2047, we were initially skeptical that we could address the memory leaking issue in (1) a Standard-compliant way and (2) without breaking ABI as <chrono> is ABI-locked under /std:c++20. However, given the suggestion by the author of this DevCom issue along with the cited permission to fail ([time.zone.db.access]), we believe we could fix the memory leaking while remaining Standard-conformant. Further, @StephanTLavavej suggests that perhaps renaming the _Global_tzdb_list variable to something like _Global_tzdb_list_v2 would allow us to make this change without breaking ABI.

Filing this issue to track the need to investigate this potential fix for this issue.

Tracked by VSO-1471620 / AB#1471620 .

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with stl/inc/chrono at the _Global_tzdb_list definition and reproduce the report using chronoleak.cpp with the provided cl command. Investigate whether cleanup can be added without violating the cited standard requirement or breaking the ABI; done means the repro no longer reports the tzdb leak while remaining ABI-compatible.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
devtools
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.