Skip to content

feat: allow freeing of ustring table for debugging cases#5193

Open
lgritz wants to merge 7 commits into
AcademySoftwareFoundation:mainfrom
lgritz:lg-ustringcleanup
Open

feat: allow freeing of ustring table for debugging cases#5193
lgritz wants to merge 7 commits into
AcademySoftwareFoundation:mainfrom
lgritz:lg-ustringcleanup

Conversation

@lgritz
Copy link
Copy Markdown
Collaborator

@lgritz lgritz commented May 13, 2026

This patch optionally frees the contents of the ustring table as the process is exiting. It's triggered one of two ways:

  • OIIO::attribute("ustring:cleanup", 1);
  • Environment variable OIIO_USTRING_CLEANUP=1

If neither is used, the teardown won't happen, thus avoiding any pointless work when it should be exiting the process.

The purpose of this is that when using certain debugging tools, the ustring table (which only grows and never frees) looks like a memory leak, even though it's by design. Someimes, it's useful to make it not appear ot leak, and you are happy for a large table to spend time pointlessly freeing all the data.

Fixes #3913

Assisted-by: Claude Code / Sonnet 4.6

@jreichel-nvidia
Copy link
Copy Markdown
Contributor

Thanks for the quick turnaround! But the allocations for entries and pool in clear() are still leaking. Are these necessary? Maybe set to nullptr, rename clear() to destroy(), and add some documentation about the purpose/consequences of that method?

@lgritz lgritz force-pushed the lg-ustringcleanup branch 3 times, most recently from fbeaff2 to 778e003 Compare May 13, 2026 17:15
@lgritz
Copy link
Copy Markdown
Collaborator Author

lgritz commented May 13, 2026

I updated with some tightening up of the allocation logic, including shrink_to_fit on the vectors.

Also, I added a print message when it does the free (for Debug builds only, and only if you have turned on the ustring cleanup), maybe you can verify that it's really running the cleanup.

If it's printing that and still complaining about leaks, is it able to tell you which allocation it is that's still never freed?

@jreichel-nvidia
Copy link
Copy Markdown
Contributor

jreichel-nvidia commented May 15, 2026

The cleanup code is running. It still shows that the calloc for entries in ustring.cpp:73 is leaking. It no longer shows a leak for pool, although I don't understand why your 2nd commit would change the behavior there ...

Edit: the print message is just for now for debugging the PR? I'd prefer if it would not print anything later, even not in Debug builds.

@lgritz
Copy link
Copy Markdown
Collaborator Author

lgritz commented May 15, 2026

I understand why. Stay tuned, will have an amendment coming soon.

@lgritz
Copy link
Copy Markdown
Collaborator Author

lgritz commented May 16, 2026

@jreichel-nvidia Amendment pushed. Any better?

@jreichel-nvidia
Copy link
Copy Markdown
Contributor

Yes, now it works! What about the debug output? Would it be possible to get rid of that?

@lgritz
Copy link
Copy Markdown
Collaborator Author

lgritz commented May 18, 2026

Yes, now it works! What about the debug output? Would it be possible to get rid of that?

Absolutely! That was only there to help you figure out for sure if the destructor was being called. Will update.

@lgritz
Copy link
Copy Markdown
Collaborator Author

lgritz commented May 18, 2026

Wait, I screwed this up. By overzealously using unique_ptr, I've actually converted the code to doing the deallocations I once wished to avoid. I need to rework this again, sorry.

lgritz added 4 commits May 18, 2026 11:12
This patch optionally frees the contents of the ustring table as the
process is exiting. It's triggered one of two ways:

- `OIIO::attribute("ustring:cleanup", 1);`
- Environment variable `OIIO_USTRING_CLEANUP=1`

If neither is used, the teardown won't happen, thus avoiding any
pointless work when it should be exiting the process.

The purpose of this is that when using certain debugging tools, the
ustring table (which only grows and never frees) looks like a memory
leak, even though it's by design. Someimes, it's useful to make it not
appear ot leak, and you are happy for a large table to spend time
pointlessly freeing all the data.

Fixes 3913

Assisted-by: Claude Code / Sonnet 4.6

Signed-off-by: Larry Gritz <lg@larrygritz.com>
* Coalesce repeated pool block allocation logic into
  allocate_pool_block().
* Change all_pools and large_allocs to vectors of std::unique_ptr so
  clearing the vec frees the pointers automatically.
* shrink_to_fit() after clearing all_pools and large_allocs.
* Initialize all TableRepMap fields by default, especially the pointers.
* When in debug mode, print when freeing the ustring table resources,
  so we are sure it happens.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
Signed-off-by: Larry Gritz <lg@larrygritz.com>
Signed-off-by: Larry Gritz <lg@larrygritz.com>
@lgritz lgritz force-pushed the lg-ustringcleanup branch from ef7a81e to ab387f8 Compare May 18, 2026 18:18
lgritz added 3 commits May 18, 2026 11:31
Signed-off-by: Larry Gritz <lg@larrygritz.com>
Signed-off-by: Larry Gritz <lg@larrygritz.com>
@lgritz lgritz force-pushed the lg-ustringcleanup branch from ab387f8 to 3ddc703 Compare May 18, 2026 18:31
@lgritz
Copy link
Copy Markdown
Collaborator Author

lgritz commented May 18, 2026

I took another pass at this, simplifying quite a bit (the whole atexit was not necessary, I could have done it in the destructors all along) and also ensuring that most of the deallocations are skipped when the special flag is not set.

Sorry to make you revisit this, @jreichel-nvidia, but can you try once more to check that what I have now still fixes all the false-positive leaks you were detecting? Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

memory leak in ustring

2 participants