-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathownership.html
333 lines (294 loc) · 20.2 KB
/
ownership.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js light">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Ownership - Tutorial</title>
<!-- Custom HTML head -->
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff" />
<link rel="icon" href="favicon.svg">
<link rel="shortcut icon" href="favicon.png">
<link rel="stylesheet" href="css/variables.css">
<link rel="stylesheet" href="css/general.css">
<link rel="stylesheet" href="css/chrome.css">
<link rel="stylesheet" href="css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
<link rel="stylesheet" href="fonts/fonts.css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" href="highlight.css">
<link rel="stylesheet" href="tomorrow-night.css">
<link rel="stylesheet" href="ayu-highlight.css">
<!-- Custom theme stylesheets -->
<link rel="stylesheet" href="visualization.css">
</head>
<body>
<!-- Provide site root to javascript -->
<script type="text/javascript">
var path_to_root = "";
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
</script>
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script type="text/javascript">
try {
var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script type="text/javascript">
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
var html = document.querySelector('html');
html.classList.remove('no-js')
html.classList.remove('light')
html.classList.add(theme);
html.classList.add('js');
</script>
<!-- Hide / unhide sidebar before it is displayed -->
<script type="text/javascript">
var html = document.querySelector('html');
var sidebar = 'hidden';
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
}
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<div class="sidebar-scrollbox">
<ol class="chapter"><li class="chapter-item expanded "><a href="motivation.html"><strong aria-hidden="true">1.</strong> Motivation</a></li><li class="chapter-item expanded "><a href="rust-basics.html"><strong aria-hidden="true">2.</strong> Rust Basics</a></li><li class="chapter-item expanded "><a href="ownership.html" class="active"><strong aria-hidden="true">3.</strong> Ownership</a></li><li class="chapter-item expanded "><a href="borrowing.html"><strong aria-hidden="true">4.</strong> Borrowing</a></li><li class="chapter-item expanded "><a href="vectors.html"><strong aria-hidden="true">5.</strong> Vectors</a></li><li class="chapter-item expanded "><a href="structs.html"><strong aria-hidden="true">6.</strong> Optional: Structures</a></li><li class="chapter-item expanded "><a href="additional_resources.html"><strong aria-hidden="true">7.</strong> Additional Resources</a></li></ol>
</div>
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
</nav>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar-hover-placeholder"></div>
<div id="menu-bar" class="menu-bar sticky bordered">
<div class="left-buttons">
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</button>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>
<h1 class="menu-title">Tutorial</h1>
<div class="right-buttons">
<a href="print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script type="text/javascript">
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<main>
<h1 id="ownership"><a class="header" href="#ownership">Ownership</a></h1>
<p>In the previous section, we considered only simple values, like integers.
However, in real-world Rust programs, we work with more complex data structures that
allocate resources on the heap. When we allocate resources, we need a strategy
for de-allocating these resources. Most programming languages use one of two
strategies:</p>
<ol>
<li>
<p>Manual Deallocation (C, C++): The programmer is responsible for explicitly
deallocating memory, e.g. using <code>free</code> in C or <code>delete</code> in C++. This is
performant but can result in critical memory safety issues such as use-after-free bugs,
double-free bugs, and memory leaks. These can cause crashes, memory corruption, and
security vulnerabilities. In fact, about 70% of security bugs in major software
products like Windows and Chrome are due to memory safety issues.</p>
</li>
<li>
<p>Garbage Collection (OCaml, Java, Python, etc.): The programmer does not have to
explicitly deallocate memory. Instead, a <em>garbage collector</em> frees (deallocates)
memory by doing a dynamic analysis that detects when no further references to the data remain
live.
This prevents memory
safety bugs. However, a garbage collector can incur sometimes substantial run-time
performance overhead.</p>
</li>
</ol>
<p>Rust uses a third strategy—a static (i.e. compile-time) ownership system.
Because this is a purely compile-time mechanism, it achieves memory safety
without the performance overhead of garbage collection!</p>
<p>The key idea is that each resource in memory has a unique <em>owner</em>,
which controls access to that resource. When the
owner's lifetime ends (it "dies"), e.g. by going out of scope,
the resource is deallocated (in Rust,
we say that the resource is <em>dropped</em>.)</p>
<h2 id="heap-allocated-strings"><a class="header" href="#heap-allocated-strings">Heap-Allocated Strings</a></h2>
<p>For example, heap-allocated strings, of type <code>String</code>, are managed by Rust's ownership system.
Consider the following example, which constructs a heap-allocated string and
prints it out.</p>
<div class="flex-container vis_block" style="position:relative; margin-left:-75px; margin-right:-75px; display: flex;">
<object type="image/svg+xml" class="string_from_print code_panel" data="assets/code_examples/string_from_print/vis_code.svg"></object>
<object type="image/svg+xml" class="string_from_print tl_panel" data="assets/code_examples/string_from_print/vis_timeline.svg" style="width: auto;" onmouseenter="helpers('string_from_print')"></object>
</div>
<p>This code prints <code>hello</code>.</p>
<p>The <code>String::from</code> function allocates a <code>String</code> on the heap. The <code>String</code> is
initialized from a provided string literal (string literals themselves have a
more primitive type, <code>&str</code>, but that detail is not important here.) Ownership
of this string resource is <em>moved</em> to the variable <code>s</code> (of type <code>String</code>) when
<code>String::from</code> returns on Line 2.</p>
<p>The <code>println!</code> macro does not cause a change in ownership (we say more about
<code>println!</code> later.)</p>
<p>At the end of the <code>main</code> function, the variable <code>s</code> goes out of scope. It has
ownership of the string resource, so Rust will <em>drop</em>, i.e. deallocate, the
resource at this point. We do not need an explicit <code>free</code> or <code>delete</code> like we
would in C or C++, nor is there any run-time garbage collection overhead. </p>
<p>Hover over the lines and arrows in the visualization next to the code example
above to see a description of the events that occur on each line of code.</p>
<h2 id="moves"><a class="header" href="#moves">Moves</a></h2>
<p>In the example above, we saw that ownership of the heap-allocated string moved
to the caller when <code>String::from</code> returned. This is one of several ways in which
ownership of a resource can move. We will now consider each situation in
more detail. </p>
<h3 id="binding"><a class="header" href="#binding">Binding</a></h3>
<p>Ownership can be moved when initializing a binding with a variable. </p>
<p>In the following example, we define a variable <code>x</code> that owns a <code>String</code>
resource. Then, we define another variable, <code>y</code>, initialized with <code>x</code>. This
causes ownership of the string resource to be moved from <code>x</code> to <code>y</code>. Note that
this behavior is different than than the copying behavior for simple types like
integers that we discussed in the previous section. </p>
<div class="flex-container vis_block" style="position:relative; margin-left:-75px; margin-right:-75px; display: flex;">
<object type="image/svg+xml" class="string_from_move_print code_panel" data="assets/code_examples/string_from_move_print/vis_code.svg"></object>
<object type="image/svg+xml" class="string_from_move_print tl_panel" data="assets/code_examples/string_from_move_print/vis_timeline.svg" style="width: auto;" onmouseenter="helpers('string_from_move_print')"></object>
</div>
<p>This code prints <code>hello</code>.</p>
<p>At the end of the function, both <code>x</code> and <code>y</code> go out of scope (their lifetimes
have ended). <code>x</code> does not own a resource anymore, so nothing special happens.
<code>y</code> does own a resource, so its resource is dropped. Hover over the
visualization to see how this works.</p>
<p>Each resource must have a unique owner, so <code>x</code> will no longer own the <code>String</code>
resource after it is moved to <code>y</code>. This means that access to the resource
through <code>x</code> is no longer possible. Think of it like handing a resource to
another person: you no longer have access to it once it has moved. For
example, the following generates a compiler error:</p>
<pre><pre class="playground"><code class="language-rust">fn main() {
let x = String::from("hello");
let y = x;
println!("{}", x) // ERROR: x does not own a resource
}
</code></pre></pre>
<p>The compiler error actually says <code>borrow of moved value: x</code> (we will discuss what
<em>borrow</em> means in the next section.)</p>
<p>If we move to a variable that has a different scope, e.g. due to curly braces,
then you can see by
hovering over the visualization that the resource is dropped at the end of <code>y</code>'s
scope rather than at the end of <code>x</code>'s scope.</p>
<div class="flex-container vis_block" style="position:relative; margin-left:-75px; margin-right:-75px; display: flex;">
<object type="image/svg+xml" class="move_different_scope code_panel" data="assets/code_examples/move_different_scope/vis_code.svg"></object>
<object type="image/svg+xml" class="move_different_scope tl_panel" data="assets/code_examples/move_different_scope/vis_timeline.svg" style="width: auto;" onmouseenter="helpers('move_different_scope')"></object>
</div>
<p>This code prints <code>hello</code> on one line and <code>Hello, world!</code> on the next.</p>
<h3 id="assignment"><a class="header" href="#assignment">Assignment</a></h3>
<p>As with binding, ownership can be moved by assignment to a mutable variable,
e.g. <code>y</code> in the following example.</p>
<div class="flex-container vis_block" style="position:relative; margin-left:-75px; margin-right:-75px; display: flex;">
<object type="image/svg+xml" class="move_assignment code_panel" data="assets/code_examples/move_assignment/vis_code.svg"></object>
<object type="image/svg+xml" class="move_assignment tl_panel" data="assets/code_examples/move_assignment/vis_timeline.svg" style="width: auto;" onmouseenter="helpers('move_assignment')"></object>
</div>
<p>When <code>y</code> acquires ownership over <code>x</code>'s resource on Line 4, the resource it
previously acquired (on Line 3) no longer has an owner, so it is dropped.</p>
<h3 id="function-call"><a class="header" href="#function-call">Function Call</a></h3>
<p>Ownership is moved into a function when it is called with a resource argument.
As an example,
below we see that ownership of the string resource in <code>main</code> is moved from <code>s</code>
to the <code>takes_ownership</code> function. Consequently, when <code>s</code> goes out of scope at
the end of <code>main</code>, there is no owned string resource to be dropped.</p>
<div class="flex-container vis_block" style="position:relative; margin-left:-75px; margin-right:-75px; display: flex;">
<object type="image/svg+xml" class="func_take_ownership code_panel" data="assets/code_examples/func_take_ownership/vis_code.svg"></object>
<object type="image/svg+xml" class="func_take_ownership tl_panel" data="assets/code_examples/func_take_ownership/vis_timeline.svg" style="width: auto;" onmouseenter="helpers('func_take_ownership')"></object>
</div>
<p>This code prints <code>hello</code>.</p>
<p>From the perspective of <code>takes_ownership</code>, it can be assumed that the argument
variable <code>some_string</code> will receive ownership of a <code>String</code> resource from the
caller (each time it is called). The argument variable <code>some_string</code> goes out of
scope at the end of the function, so the resource that it owns is dropped at
that point.</p>
<h3 id="return"><a class="header" href="#return">Return</a></h3>
<p>Finally, ownership can be returned from a function. </p>
<p>In the following example, <code>f</code> allocates a <code>String</code> and returns it to the
caller. Ownership is moved from <code>x</code> to the caller, so there is no owned resource
to be dropped at the end of <code>f</code>. Instead, the resource is dropped when the new
owner, <code>s</code>, goes out of scope at the end of <code>main</code>. (If the <code>String</code> were
dropped at the end of <code>f</code>, there would be a use-after-free bug in <code>main</code> on Line
9!)</p>
<div class="flex-container vis_block" style="position:relative; margin-left:-75px; margin-right:-75px; display: flex;">
<object type="image/svg+xml" class="move_func_return code_panel" data="assets/code_examples/move_func_return/vis_code.svg"></object>
<object type="image/svg+xml" class="move_func_return tl_panel" data="assets/code_examples/move_func_return/vis_timeline.svg" style="width: auto;" onmouseenter="helpers('move_func_return')"></object>
</div>
<p>This code prints <code>hello</code>.</p>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="rust-basics.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="borrowing.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a rel="prev" href="rust-basics.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="borrowing.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</nav>
</div>
<script type="text/javascript">
window.playground_copyable = true;
</script>
<script src="elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
<script src="mark.min.js" type="text/javascript" charset="utf-8"></script>
<script src="searcher.js" type="text/javascript" charset="utf-8"></script>
<script src="clipboard.min.js" type="text/javascript" charset="utf-8"></script>
<script src="highlight.js" type="text/javascript" charset="utf-8"></script>
<script src="book.js" type="text/javascript" charset="utf-8"></script>
<!-- Custom JS scripts -->
<script type="text/javascript" src="helpers.js"></script>
</body>
</html>