You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: manual/object_ownership/index.md
+41-41Lines changed: 41 additions & 41 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,9 +7,9 @@ toc: true
7
7
toc_sticky: true
8
8
---
9
9
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.
13
13
14
14
By the end of this page you will know why
15
15
{% highlight C++ %}
@@ -19,41 +19,21 @@ void ownership() {
19
19
hist->Draw();
20
20
}
21
21
{% endhighlight %}
22
-
shows an empty canvas after calling `ownership()`.
22
+
shows an empty canvas in ROOT 6 after calling `ownership()`.
23
23
24
-
## Ownership by current directory `gDirectory`
24
+
## ROOT 6: Ownership by the current directory `gDirectory`
25
25
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).
27
27
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.
28
29
29
30
_**Example**_
30
31
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.
32
35
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.
57
37
{% highlight C++ %}
58
38
void ownership() {
59
39
TFile file("file.root");
@@ -64,30 +44,50 @@ void ownership() {
64
44
}
65
45
{% endhighlight %}
66
46
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()`:
68
48
69
49
{% 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);
75
51
{% endhighlight %}
76
52
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()`:
78
65
79
66
{% highlight C++ %}
80
67
std::unique_ptr<TH1> hist;
81
68
void ownership() {
82
-
TH1::AddDirectory(false);
69
+
ROOT::Experimental::DisableObjectAutoRegistration(); // Make ROOT 6 behave like ROOT 7
83
70
TFile file("file.root");
84
71
hist.reset(new TH1F("hist", "hist", 10, 0., 1.));
85
-
// or, instead of TH1::AddDirectory(false):
86
-
// hist->SetDirectory(nullptr);
87
72
hist->Draw();
88
73
}
89
74
{% endhighlight %}
90
75
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
+
91
91
## Ownership by `gROOT`
92
92
93
93
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