Skip to content

Commit 00153ef

Browse files
committed
Update the page on ownership.
1 parent 43a4e09 commit 00153ef

1 file changed

Lines changed: 41 additions & 41 deletions

File tree

manual/object_ownership/index.md

Lines changed: 41 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ toc: true
77
toc_sticky: true
88
---
99

10-
An object ownership means the permission to delete it.
11-
Modern code should use local variables or `std::unique_ptr`; but some of ROOT's types are managed differently.
12-
To prevent memory leaks and multiple attempts to delete an object, you need to know which objects are owned by ROOT and which are owned by you.
10+
With "owning" an object, we mean being responsible for its lifetime, that is, taking care of deleting it when it's no longer in use.
11+
For new code, we advise to use objects on the stack or smart pointers like `std::unique_ptr`; but some of ROOT's types historically were managed differently.
12+
To prevent memory leaks and multiple attempts to delete an object, you need to know which objects are owned by ROOT and which are owned by the user.
1313

1414
By the end of this page you will know why
1515
{% highlight C++ %}
@@ -19,41 +19,21 @@ void ownership() {
1919
hist->Draw();
2020
}
2121
{% endhighlight %}
22-
shows an empty canvas after calling `ownership()`.
22+
shows an empty canvas in ROOT 6 after calling `ownership()`.
2323

24-
## Ownership by current directory `gDirectory`
24+
## ROOT 6: Ownership by the current directory `gDirectory`
2525

26-
When a [histogram](https://root.cern/doc/master/group__Hist.html){:target="_blank"}, a {% include ref class="TTree" %} or a {% include ref class="TEventList" %} is created, it is added by default to the list of objects in the current directory [`gDirectory`](https://root.cern/doc/master/classTDirectory.html).
26+
When a [histogram](https://root.cern/doc/master/group__Hist.html){:target="_blank"}, a {% include ref class="TTree" %} or a {% include ref class="TEventList" %} is created in ROOT 6, it registers itself to the current directory [`gDirectory`](https://root.cern/doc/master/classTDirectory.html).
2727
In many cases that is the {% include ref class="TFile" %} that was opened most recently.
28+
This directory now owns the object, and will take care of deleting it.
2829

2930
_**Example**_
3031

31-
Changing the directory of a histogram (same applies to trees and event lists):
32+
In ROOT 6, when you create a {% include ref class="TFile" %} object, it becomes the current directory (`gDirectory`).
33+
If you subsequently create a new histogram, this histogram is owned by the current directory:
34+
the histogram is deleted when the {% include ref class="TFile" %} object is destructed.
3235

33-
{% highlight C++ %}
34-
h->SetDirectory(newDir);
35-
{% endhighlight %}
36-
37-
You can remove a histogram from a directory by using `SetDirectory(nullptr)`. Once a histogram is removed from the directory, it will not be deleted when the directory is deleted. Instead, you have to delete the histogram yourself to prevent memory leaks.
38-
39-
### Disabling ROOT's automatic ownership management for histograms
40-
41-
To prevent histograms from being added to the current directory, call the static function
42-
43-
{% highlight C++ %}
44-
TH1::AddDirectory(kFALSE);
45-
{% endhighlight %}
46-
47-
Now you own all histogram objects and you will need to delete them, for instance through the use of `std::unique_ptr`.
48-
You can still set the directory of a histogram by calling `SetDirectory()` once it has been created.
49-
50-
_**Example**_
51-
52-
When you create a {% include ref class="TFile" %} object, it becomes the current directory (`gDirectory`).
53-
If you subsequently create a new histogram, this histogram is now owned by the current directory:
54-
the histogram is deleted when the {% include ref class="TFile" %} object destructed.
55-
56-
In the following example, only an empty canvas is shown because the {% include ref class="TH1F" %} histogram is owned by the current directory (`gDirectory`) corresponding to the {% include ref class="TFile" %} object.
36+
In the following example, only an empty canvas is shown because the {% include ref class="TH1F" %} histogram is owned by the {% include ref class="TFile" %} object.
5737
{% highlight C++ %}
5838
void ownership() {
5939
TFile file("file.root");
@@ -64,30 +44,50 @@ void ownership() {
6444
}
6545
{% endhighlight %}
6646

67-
In the following example, the canvas shows the histogram because the {% include ref class="TH1F" %} histogram is created before the {% include ref class="TFile" %} is opened; the `TFile` does not own it.
47+
To change the directory of a histogram (same applies to trees and event lists), one can use `SetDirectory()`:
6848

6949
{% highlight C++ %}
70-
void ownership() {
71-
auto hist = new TH1F("hist", "hist", 10, 0., 1.);
72-
TFile file("file.root");
73-
hist->Draw();
74-
}
50+
h->SetDirectory(newDir);
7551
{% endhighlight %}
7652

77-
Finally, this canvas shows the histogram because it is owned by a `unique_ptr` which lives longer than the function `ownership()`:
53+
One can remove a histogram from a directory by using `SetDirectory(nullptr)`. Once a histogram is removed from the directory, it will not be deleted when the directory is deleted. Instead, you have to delete the histogram yourself to prevent memory leaks.
54+
55+
## ROOT 7: Ownership by the user
56+
In ROOT 7, the ownership model will be changed to explicitly hand ownership to the user, because objects such as histograms will not anymore register themselves to the current directory.
57+
Users can still decide to pass the ownership to ROOT directories or ROOT files if they want these to manage an object using `SetDirectory(someDirectory)`.
58+
59+
The ROOT 7 behaviour can be tested already in ROOT 6 using [`DisableObjectAutoRegistration()`](https://root.cern/doc/master/namespaceROOT_1_1Experimental.html#a74fae8f88965b8c79dfbd25bebbce3a4).
60+
Conversely, ROOT 7 can be switched to ROOT 6 behaviour using [`EnableObjectAutoRegistration()`](https://root.cern/doc/master/namespaceROOT_1_1Experimental.html#a15c715c36cf189a6d15ae366da307f23).
61+
62+
_**Example**_
63+
64+
In ROOT 7 mode, the canvas shows the histogram because it is owned by the `unique_ptr` which lives longer than the function `ownership()`:
7865

7966
{% highlight C++ %}
8067
std::unique_ptr<TH1> hist;
8168
void ownership() {
82-
TH1::AddDirectory(false);
69+
ROOT::Experimental::DisableObjectAutoRegistration(); // Make ROOT 6 behave like ROOT 7
8370
TFile file("file.root");
8471
hist.reset(new TH1F("hist", "hist", 10, 0., 1.));
85-
// or, instead of TH1::AddDirectory(false):
86-
// hist->SetDirectory(nullptr);
8772
hist->Draw();
8873
}
8974
{% endhighlight %}
9075

76+
### Permanently switching to ROOT 7 mode (ownership by the user)
77+
In ROOT v6.40, ROOT can be permanently switched to use ROOT 7 mode using environment variables or by setting defaults in a .rootrc file.
78+
For details, consult [`DisableObjectAutoRegistration()`](https://root.cern/doc/master/namespaceROOT_1_1Experimental.html#a74fae8f88965b8c79dfbd25bebbce3a4)
79+
80+
### `TH1::AddDirectory`
81+
82+
To prevent histograms from being added to the current directory, users could in the past call
83+
84+
{% highlight C++ %}
85+
TH1::AddDirectory(false);
86+
{% endhighlight %}
87+
88+
We advise to instead use `DisableObjectAutoRegistration()`, because it is thread local, and covers more objects such as TGraph2D, TEfficiency, RooPlot and similar.
89+
For details, see the documentation of [`DisableObjectAutoRegistration()`](https://root.cern/doc/master/namespaceROOT_1_1Experimental.html#a74fae8f88965b8c79dfbd25bebbce3a4).
90+
9191
## Ownership by `gROOT`
9292

9393
The global [`gROOT`](https://root.cern/doc/master/classTROOT.html) object has several utility collections, for instance of all functions `gROOT->GetListOfFunction()`, canvases `gROOT->GetListOfCanvases()`, and files `gROOT->GetListOfFiles()`.

0 commit comments

Comments
 (0)