1 00:00:00,000 --> 00:00:08,000 [No Audio] 2 00:00:08,001 --> 00:00:10,533 Welcome back again in the new tutorial. As 3 00:00:10,600 --> 00:00:13,000 announced in the last tutorial, this tutorial 4 00:00:13,033 --> 00:00:15,300 is specifically designed to answer the 5 00:00:15,301 --> 00:00:18,100 question that is, why the ownership is being 6 00:00:18,101 --> 00:00:20,933 transferred or moved in case of non-primitive 7 00:00:20,966 --> 00:00:24,300 types such as strings and vectors? To answer 8 00:00:24,301 --> 00:00:26,800 this, we will be looking at how the programs 9 00:00:26,833 --> 00:00:29,800 are being handled inside the memory, and how 10 00:00:29,833 --> 00:00:32,333 they use and interact with the memory of the 11 00:00:32,366 --> 00:00:36,000 computer system. Memory is one of the most 12 00:00:36,001 --> 00:00:39,033 important and crucial resource on our machine 13 00:00:39,100 --> 00:00:41,500 or computer system, and it is always good to 14 00:00:41,533 --> 00:00:44,300 know the architecture of the memory, that is 15 00:00:44,333 --> 00:00:46,500 the way operating system manages the memory, 16 00:00:46,501 --> 00:00:49,300 and the way memory is accessible to us as 17 00:00:49,333 --> 00:00:52,533 programmers. The memory that is assigned to a 18 00:00:52,566 --> 00:00:54,433 program or application in a typical 19 00:00:54,466 --> 00:00:56,500 architecture can be divided into four 20 00:00:56,533 --> 00:00:59,500 segments. One segment of the memory is 21 00:00:59,533 --> 00:01:01,933 assigned to store the instructions that need 22 00:01:01,966 --> 00:01:05,800 to be executed or in simple word, the program 23 00:01:05,833 --> 00:01:08,733 instructions and code. Another section 24 00:01:08,800 --> 00:01:11,600 stores all the Static or Global variables, 25 00:01:12,033 --> 00:01:14,433 these variables have the whole lifetime of a 26 00:01:14,466 --> 00:01:16,700 program application and are accessible 27 00:01:16,701 --> 00:01:18,900 anywhere during the whole lifecycle of the 28 00:01:18,901 --> 00:01:22,500 program, as long as it is in execution. 29 00:01:23,800 --> 00:01:26,500 They are visible to all parts of the program, and 30 00:01:26,533 --> 00:01:28,433 are declared before the start of the main 31 00:01:28,466 --> 00:01:30,800 function at the top of the program and are 32 00:01:30,801 --> 00:01:34,300 typically constants. The third section of the 33 00:01:34,333 --> 00:01:36,733 memory, stores all the information 34 00:01:36,766 --> 00:01:39,100 regarding the function calls and the local 35 00:01:39,101 --> 00:01:41,633 variables defined inside these functions, and 36 00:01:41,666 --> 00:01:44,733 in the context of Rust, all the primitive 37 00:01:44,800 --> 00:01:48,300 type variables. The amount of memory that is 38 00:01:48,333 --> 00:01:50,800 set aside for these three segments, that is 39 00:01:50,801 --> 00:01:53,600 the Text segment, the Global variable segment, 40 00:01:53,601 --> 00:01:56,133 and the Stack does not grow while the 41 00:01:56,166 --> 00:01:58,700 application is running. Let us first 42 00:01:58,701 --> 00:02:01,733 understand, how these three segments of memory 43 00:02:01,766 --> 00:02:05,000 are used when a program executes. We will 44 00:02:05,033 --> 00:02:08,166 come back to the Heap in a while. Suppose we 45 00:02:08,199 --> 00:02:11,032 have this simple program in Rust, we have one 46 00:02:11,066 --> 00:02:13,400 Global variable in this program called 47 00:02:13,401 --> 00:02:16,100 MAX_VALUE, then inside the main 48 00:02:16,133 --> 00:02:17,933 function, we are defining two variables 49 00:02:17,966 --> 00:02:21,633 called x and y to the values of 2 and 4 respectively. 50 00:02:22,100 --> 00:02:23,833 Next, we are calling the 51 00:02:23,866 --> 00:02:25,700 function square_num with these 52 00:02:25,733 --> 00:02:28,600 two values as input, which calls another 53 00:02:28,601 --> 00:02:31,833 function called square and passes to it the 54 00:02:31,866 --> 00:02:34,200 summation of the two values which is 55 00:02:34,201 --> 00:02:37,433 computing the square of the passed summation value. 56 00:02:38,433 --> 00:02:40,100 Let us see what will happen to the 57 00:02:40,133 --> 00:02:42,300 memory when this program is being executed. 58 00:02:42,900 --> 00:02:44,933 When the program is being executed, the three 59 00:02:44,966 --> 00:02:47,633 pieces of memory will be allotted to it 60 00:02:47,833 --> 00:02:49,900 consisting of the Code or Text part, the 61 00:02:49,933 --> 00:02:52,300 Static or Global portion and the Stack portion. 62 00:02:53,900 --> 00:02:55,833 Since the Text part will most 63 00:02:55,866 --> 00:02:57,700 probably not change during the execution of 64 00:02:57,701 --> 00:03:00,100 the program, so we will not explain its usage, 65 00:03:00,300 --> 00:03:02,700 and I will only show up the diagram that 66 00:03:02,701 --> 00:03:04,533 contains the two portion of the memory. 67 00:03:05,633 --> 00:03:08,600 Now let us see what happens to these two parts 68 00:03:08,601 --> 00:03:11,700 when a program executes. Okay, when the program 69 00:03:11,701 --> 00:03:15,933 starts executing, first the main function is invoked. 70 00:03:16,400 --> 00:03:18,700 When the main method is invoked, some 71 00:03:18,701 --> 00:03:21,433 amount of memory from the Stack is 72 00:03:21,466 --> 00:03:23,300 allocated for execution of main. 73 00:03:23,900 --> 00:03:26,333 Since we have one Global variable in this code, so this 74 00:03:26,366 --> 00:03:29,833 variable will reside in the Global section of the memory. 75 00:03:31,300 --> 00:03:32,933 The amount of memory allocated in 76 00:03:32,966 --> 00:03:35,733 Stack for execution of main function, can also 77 00:03:35,766 --> 00:03:39,000 be called the Stack Frame for the main function. 78 00:03:39,800 --> 00:03:42,100 All the variables, arguments to 79 00:03:42,101 --> 00:03:44,800 different functions, the main is calling and 80 00:03:44,801 --> 00:03:46,500 the information where the function should 81 00:03:46,533 --> 00:03:49,800 return back to, all this information is stored 82 00:03:49,801 --> 00:03:52,400 within the Stack Frame. The size of the 83 00:03:52,433 --> 00:03:56,100 Stack Frame for a method or for a function, is 84 00:03:56,101 --> 00:03:58,433 calculated when the program is compiling. 85 00:03:59,233 --> 00:04:01,833 Let me add the names of the variables x,y, 86 00:04:02,033 --> 00:04:04,300 and the name of the function main to this 87 00:04:04,301 --> 00:04:07,933 Stack Frame. Now when the main calls 88 00:04:07,934 --> 00:04:11,400 square_sum function, then the Stack Frame 89 00:04:11,433 --> 00:04:14,500 is allocated for the call to square_sum. 90 00:04:15,100 --> 00:04:16,366 Let me draw a line to 91 00:04:16,367 --> 00:04:19,899 indicate the Stack Frame. All that local 92 00:04:19,933 --> 00:04:22,000 variables of this functions including the 93 00:04:22,001 --> 00:04:24,200 variable of num1 and num2, and the 94 00:04:24,201 --> 00:04:26,300 result will be assigned to memory from this 95 00:04:26,301 --> 00:04:29,533 particular Stack Frame. So I will add to this 96 00:04:29,566 --> 00:04:32,400 Stack, the local variable and the function name. 97 00:04:32,700 --> 00:04:34,833 Next, when the square_sum 98 00:04:34,834 --> 00:04:38,000 calls the square function, again another Stack 99 00:04:38,033 --> 00:04:40,200 Frame will be assigned to the square function, 100 00:04:40,201 --> 00:04:42,433 which will store its local variables, which in 101 00:04:42,466 --> 00:04:44,833 this case is the variable num. 102 00:04:46,300 --> 00:04:48,800 Let us make a new Stack Frame and add the 103 00:04:48,801 --> 00:04:50,800 relevant variables of the function to it. 104 00:04:52,000 --> 00:04:55,633 Now the important point to note is that, at any 105 00:04:55,666 --> 00:04:57,900 time during the execution of the program, the 106 00:04:57,901 --> 00:05:00,300 function at the top of the stack is in execution, 107 00:05:00,333 --> 00:05:03,033 and the rest are kind of paused or in 108 00:05:03,034 --> 00:05:05,300 waiting condition. They are waiting for the 109 00:05:05,301 --> 00:05:07,433 function above to return something, and then 110 00:05:07,500 --> 00:05:10,600 it will resume their respective execution. 111 00:05:11,333 --> 00:05:13,100 Now as soon as the square function will 112 00:05:13,101 --> 00:05:15,700 return and complete its job, it will be 113 00:05:15,733 --> 00:05:18,200 cleared from the Stack memory, and now 114 00:05:18,201 --> 00:05:20,933 square_sum function will resume. I will delete 115 00:05:20,966 --> 00:05:24,000 it from the Stack, so that we have an exact 116 00:05:24,001 --> 00:05:27,000 idea of what is happening. Next, when the 117 00:05:27,001 --> 00:05:29,500 square_sum function ends, its memory will be 118 00:05:29,533 --> 00:05:31,900 released. So let me update the memory. 119 00:05:32,700 --> 00:05:35,400 Finally, when the main completes, the Stack 120 00:05:35,433 --> 00:05:38,433 will become empty, and at this stage, the 121 00:05:38,466 --> 00:05:41,300 Global section of the memory will also become empty. 122 00:05:42,700 --> 00:05:45,000 Okay, here is an important point, when 123 00:05:45,001 --> 00:05:47,733 our program starts, the operating system 124 00:05:47,766 --> 00:05:50,600 allocates some amount of reserved space, 125 00:05:50,601 --> 00:05:52,566 let's say 1 or 2 MB depending on the 126 00:05:52,567 --> 00:05:55,500 operating system. The actual allocation of 127 00:05:55,501 --> 00:05:57,800 the Stack Frames and the 128 00:05:57,833 --> 00:05:59,933 actual allocation of the local variables 129 00:05:59,966 --> 00:06:03,100 happen from the Stack during runtime. And if 130 00:06:03,101 --> 00:06:05,000 the Stack grows beyond the reserved memory 131 00:06:05,001 --> 00:06:08,433 for the Stack for example. So in that case, 132 00:06:08,434 --> 00:06:11,633 this is called Stack Overflow, and in this 133 00:06:11,666 --> 00:06:15,233 case, our program will crash. One common case 134 00:06:15,266 --> 00:06:17,300 of Stack Overflow is, when you keep on 135 00:06:17,333 --> 00:06:19,933 declaring variables inside an infinite loop. 136 00:06:20,133 --> 00:06:22,700 Since we have not covered loops yet, so it 137 00:06:22,701 --> 00:06:25,300 will start to make sense in the next section. 138 00:06:26,133 --> 00:06:28,133 All data stored on the Stack must have, 139 00:06:28,166 --> 00:06:31,600 unknown fixed size, data with an unknown size 140 00:06:31,601 --> 00:06:34,333 at compile time or a size that might change 141 00:06:34,334 --> 00:06:36,700 must be stored on the Heap instead. 142 00:06:37,500 --> 00:06:40,333 You may have guessed correctly that, when we 143 00:06:40,334 --> 00:06:42,933 we are working with strings or vectors, they must 144 00:06:42,966 --> 00:06:45,433 be stored in the Heap. The Heap is less 145 00:06:45,466 --> 00:06:48,033 organized in the sense that, things are not 146 00:06:48,034 --> 00:06:50,333 added to the Heap in sequential order just 147 00:06:50,366 --> 00:06:53,633 like we added them in the Stack. When you put 148 00:06:53,700 --> 00:06:56,366 data on the Heap, you request a certain 149 00:06:56,367 --> 00:06:58,700 amount of space. The operating system finds 150 00:06:58,733 --> 00:07:02,400 an empty spot in the Heap, that is big 151 00:07:02,401 --> 00:07:05,333 enough and marks it as being in use, and 152 00:07:05,366 --> 00:07:07,600 returns a pointer which is the address of the 153 00:07:07,633 --> 00:07:10,733 application. The involvement of operating 154 00:07:10,766 --> 00:07:13,400 system in case of stay allocation is minimal. 155 00:07:13,933 --> 00:07:16,300 The involvement of operating system 156 00:07:16,301 --> 00:07:18,833 creates extra overhead in case of Heap. 157 00:07:19,433 --> 00:07:21,400 Although there are many details as to how the 158 00:07:21,433 --> 00:07:23,766 Heap is actually implemented, but from the 159 00:07:23,767 --> 00:07:26,200 programmer perspective, the easiest way to 160 00:07:26,201 --> 00:07:29,700 comprehend it, is to consider it as a free 161 00:07:29,701 --> 00:07:32,400 large pool of memory or free store of memory 162 00:07:32,433 --> 00:07:35,700 that is available for us to use. Let us see 163 00:07:35,733 --> 00:07:38,300 how our program will store a simple string 164 00:07:38,333 --> 00:07:41,133 inside a Heap. I will add one more block to 165 00:07:41,166 --> 00:07:43,700 the present the Heap memory. Now consider 166 00:07:43,701 --> 00:07:46,433 this simple program, where we have one integer 167 00:07:46,466 --> 00:07:49,800 variable and one string variable. Next, we 168 00:07:49,833 --> 00:07:52,100 are moving the value of s1 into s2, 169 00:07:52,133 --> 00:07:55,000 which will invalidate the variable s1 as 170 00:07:55,300 --> 00:07:57,300 we have pointed out in the previous tutorial. 171 00:07:57,633 --> 00:08:00,233 Afterwards, we have another variable which is 172 00:08:00,266 --> 00:08:02,800 s3, which is basically a reference to s2. 173 00:08:03,000 --> 00:08:05,600 And finally, we have a variable of s4 174 00:08:05,633 --> 00:08:10,133 which is a clone of s2. Let us see how they 175 00:08:10,166 --> 00:08:13,000 are manipulated inside the memory, or in other 176 00:08:13,001 --> 00:08:15,600 words inside the Heap. When this program 177 00:08:15,633 --> 00:08:18,200 executes, we will have a Stack Frame that is 178 00:08:18,201 --> 00:08:20,333 being allocated to the main function. The 179 00:08:20,366 --> 00:08:23,700 value of variable x will be first pushed onto 180 00:08:23,701 --> 00:08:26,333 the Stack Frame, then we encounter the 181 00:08:26,366 --> 00:08:28,733 variable s1, which is a string variable. 182 00:08:28,900 --> 00:08:31,500 Since this variable can grow in size, 183 00:08:31,533 --> 00:08:34,265 therefore, we need to allocate it memory from 184 00:08:34,299 --> 00:08:37,400 the Heap. The operating system will request 185 00:08:37,433 --> 00:08:40,700 to assign memory for the string, that is large 186 00:08:40,701 --> 00:08:43,400 enough to store the entire string. Once the 187 00:08:43,401 --> 00:08:45,533 memory is assigned, a pointer to that 188 00:08:45,566 --> 00:08:48,200 particular memory location will be stored 189 00:08:48,233 --> 00:08:51,500 inside the Stack. Now this means that, the 190 00:08:51,501 --> 00:08:53,933 variable s1 is a pointer which is stored 191 00:08:53,966 --> 00:08:58,300 on the Stack, but its contents are stored on the Heap. 192 00:08:58,833 --> 00:09:00,900 To fetch the contents, we will be 193 00:09:00,901 --> 00:09:03,300 following the pointer in memory. Now in 194 00:09:03,333 --> 00:09:05,700 contrast to some other programming languages, 195 00:09:05,933 --> 00:09:08,900 if we assign another pointer to s1, that is 196 00:09:08,901 --> 00:09:11,200 s1 is pointing to some other memory 197 00:09:11,233 --> 00:09:14,033 location, or s1 is no more valid, then the 198 00:09:14,066 --> 00:09:16,300 previous values in the memory will remain 199 00:09:16,301 --> 00:09:19,300 until the programmer explicitly used some 200 00:09:19,301 --> 00:09:21,133 command for freeing up the Heap 201 00:09:21,166 --> 00:09:23,300 space, that is being allocated to it. 202 00:09:24,833 --> 00:09:27,600 If for some reason, the programmers are unable to 203 00:09:27,601 --> 00:09:29,733 free this free space, for instance, they 204 00:09:29,766 --> 00:09:32,200 forget to free it by writing explicit 205 00:09:32,201 --> 00:09:34,900 commands, then that memory location will 206 00:09:34,901 --> 00:09:37,233 become inaccessible for our operating system 207 00:09:37,266 --> 00:09:38,933 to be used for some other purposes. 208 00:09:39,600 --> 00:09:42,000 The operating system will keep on assuming that 209 00:09:42,001 --> 00:09:44,600 the memory is being used by the program, while 210 00:09:44,601 --> 00:09:47,800 there is no variable in our program, which is 211 00:09:47,801 --> 00:09:50,700 pointing to that particular memory location. 212 00:09:51,500 --> 00:09:53,733 Rust, on the other hand, has a very 213 00:09:53,766 --> 00:09:56,300 different approach, and it deallocates the 214 00:09:56,301 --> 00:09:59,600 space as soon as the variable goes out of scope, 215 00:09:59,633 --> 00:10:02,500 and will not allow this to happen. 216 00:10:03,433 --> 00:10:05,733 Now let us see what will happen when the 217 00:10:05,800 --> 00:10:08,833 next line gets executed. This line will 218 00:10:08,900 --> 00:10:11,100 transfer the ownership by moving the value 219 00:10:11,101 --> 00:10:14,133 into the variable s2. What basically 220 00:10:14,166 --> 00:10:16,233 happens behind the scene is that, the Rust 221 00:10:16,266 --> 00:10:19,700 will delete the pointer s1. Let me delete 222 00:10:19,701 --> 00:10:22,600 the pointer s1 from the Stack, and we'll 223 00:10:22,633 --> 00:10:25,600 create another pointer called s2, which 224 00:10:25,601 --> 00:10:28,100 will point to the same resource in memory. 225 00:10:28,933 --> 00:10:30,200 Let me draw this. 226 00:10:30,201 --> 00:10:32,466 [No Audio] 227 00:10:32,467 --> 00:10:34,300 Moreover, the Rust will not 228 00:10:34,301 --> 00:10:36,900 make a copy of this string, because making a 229 00:10:36,901 --> 00:10:39,300 new copy will require extra overhead of 230 00:10:39,301 --> 00:10:41,100 consulting the operating system which 231 00:10:41,133 --> 00:10:44,600 allocates the memory. Moreover, by not making a 232 00:10:44,633 --> 00:10:47,800 new copy and ensuring that there is an owner, 233 00:10:47,801 --> 00:10:51,400 it also avoids the danger of having some 234 00:10:51,433 --> 00:10:54,300 memory, which is not being used inside the program. 235 00:10:54,733 --> 00:10:56,933 Next, when we create s3, another 236 00:10:56,966 --> 00:10:59,033 variable to the Stack will be pushed, which 237 00:10:59,066 --> 00:11:01,400 will be pointing to the same resource as that 238 00:11:01,433 --> 00:11:04,633 of s2. Let us draw this for a better understanding. 239 00:11:05,700 --> 00:11:07,733 Finally, the final 240 00:11:07,766 --> 00:11:09,500 statement will create a new copy of the 241 00:11:09,501 --> 00:11:11,500 resource, which will again request the 242 00:11:11,501 --> 00:11:13,800 operating system to allocate a new memory. 243 00:11:14,200 --> 00:11:16,700 In this case now, we will have another variable 244 00:11:16,733 --> 00:11:18,500 s4 in the Stack which will be pointing 245 00:11:18,533 --> 00:11:21,500 towards a new memory block and not to the 246 00:11:21,501 --> 00:11:26,100 value of s2, let us draw this also. You may 247 00:11:26,101 --> 00:11:29,600 have noticed that, by having the concept of 248 00:11:29,601 --> 00:11:31,233 ownership, the Rust ensures 249 00:11:31,234 --> 00:11:34,000 that we use the Heap more effectively. 250 00:11:34,300 --> 00:11:37,300 In particular, we only make a copy when it's 251 00:11:37,333 --> 00:11:40,733 being explicitly asked for. By ensuring that 252 00:11:40,766 --> 00:11:43,133 there is always an owner, Rust ensures the 253 00:11:43,166 --> 00:11:46,100 memory safety. These features will become 254 00:11:46,133 --> 00:11:48,933 more obvious to us as we progress in the course. 255 00:11:50,500 --> 00:11:52,500 That brings us to the end of this tutorial. 256 00:11:52,633 --> 00:11:54,733 The question we started with was, 257 00:11:54,833 --> 00:11:57,400 why the ownership is being transferred or 258 00:11:57,401 --> 00:12:00,033 moved in case of non-primitive types such as 259 00:12:00,066 --> 00:12:02,400 strings and vectors? And we got the answer. 260 00:12:03,100 --> 00:12:05,333 This is because, they are being stored in the 261 00:12:05,366 --> 00:12:08,900 Heap, and using the Heap involves the 262 00:12:08,901 --> 00:12:11,300 overhead of asking the operating system for 263 00:12:11,301 --> 00:12:13,800 allocation of memory, and returning a pointer 264 00:12:13,801 --> 00:12:16,633 to that particular location. Moreover, it 265 00:12:16,700 --> 00:12:19,900 also requires memory safety features. We will 266 00:12:19,933 --> 00:12:22,200 cover the memory safety feature later on in 267 00:12:22,201 --> 00:12:25,100 the course also, in some detail. In the next 268 00:12:25,101 --> 00:12:27,200 tutorial, we will be covering the details of 269 00:12:27,233 --> 00:12:29,700 ownership in the context of functions. 270 00:12:30,033 --> 00:12:33,133 Do come back for that, because we have now 271 00:12:33,166 --> 00:12:35,033 some good understanding and good foundations 272 00:12:35,066 --> 00:12:36,800 to learn more about ownership. 273 00:12:37,166 --> 00:12:39,933 Until next tutorial, Happy Rust programming. 274 00:12:39,934 --> 00:12:47,400 [No Audio]