Skip to content

[PyROOT] Take ownership of objects returned by TDirectoryFile.Get that are not owned by the directory - #23798

Open
jmcarcell wants to merge 3 commits into
root-project:masterfrom
jmcarcell:tdirectoryfile-get-ownership
Open

jmcarcell wants to merge 3 commits into
root-project:masterfrom
jmcarcell:tdirectoryfile-get-ownership

Conversation

@jmcarcell

@jmcarcell jmcarcell commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

This Pull request:

Changes or fixes:

TDirectoryFile.Get in Python reads the object with GetObjectChecked() and binds the returned pointer without taking ownership. Objects that are not added to the directory's list are therefore never deleted. This covers non-TObjects like std::vector or ROOT::RNTuple, and TObjects without DirectoryAutoAdd, like TGraph or TObjString. Calling Get again creates a new copy each time, so memory grows. For example, reading the RNTuple anchor of a file:

Direct leak of 72 byte(s) in 1 object(s) allocated from:
    #0 0x7f8f6c92d85c in operator new(unsigned long)
    #1 0x7b8f61cd6d5d in ROOT::new_ROOTcLcLRNTuple(void*)

Python now takes ownership of the returned object, except when the directory holds it in its list. That is the case for histograms, trees and subdirectories, which keep being owned by the directory as before. The fallback for when no key is found is not changed, because it returns objects that are already in memory and owned by someone else. Checking the directory's list (a THashList) adds about 4 µs to each Get call, and this does not depend on the number of objects in the directory.

I added a test to tdirectory_tfile.py that checks that a TGraph, a TObjString and a std::vector read with Get are owned by Python, and that a TH1F, a TTree and a subdirectory are not and are still usable from the directory after the Python object is deleted. The test fails without the fix.

Checklist:

  • tested changes locally
  • updated the docs (if necessary)

I also checked that calling Get many times no longer makes memory grow for TGraph, TObjString, std::vector and RNTuple, and that tdirectory_tfile.py passes under ASan with no double deletes.

This PR fixes #16178

@vepadulano vepadulano left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! In principle LGTM, but see some comments for the tests

Comment thread bindings/pyroot/pythonizations/test/tdirectory_tfile.py Outdated
Comment thread bindings/pyroot/pythonizations/test/tdirectory_tfile.py Outdated
Comment thread bindings/pyroot/pythonizations/test/tdirectory_tfile.py Outdated
jmcarcell and others added 2 commits October 22, 2026 15:31
Co-authored-by: Vincenzo Eduardo Padulano <v.e.padulano@gmail.com>

This branch has not been deployed

No deployments
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.

[PyROOT] Memory leak in _TDirectoryFile_Get

2 participants