preface

Rust is a system level programming language developed by mozilla. Its main features are high performance (as good as c++), safe operation, and complete documentation and toolchain. Rust also has many front-end applications. It is currently the programming language with the highest support for webAssembly ecology. This may be due to historical reasons. The predecessor of WebAssembly, ASM. In addition, the well-known deno’s underlying implementation is also written on rust. This paper mainly introduces the killer ownership, which makes many beginners feel confused and have doubts about writing rust code

What is the Ownership

Ownership is a set of memory management strategies for rust programs. Memory management is a perennial topic for programming languages, some of which have their own garbage collection (GC), which tracks and cleans up memory variables that are no longer used, such as the js we often write. For a language without GC, it is necessary for the developer to determine in the code which variables are no longer used and manually clear them. This is obviously a big burden for the developer, and can easily lead to memory leaks or exceptions such as null Pointers if not handled properly, typically in C/C ++. Rust takes a different approach to memory management. It checks for memory problems in your program at compile time according to ownership rules to ensure that your program is safe and stable at runtime. Ownership rules can be briefly summarized as the following three points:

  1. Every variable assigned in rust is the owner of that value
  2. Only one owner can exist at a time for a value
  3. The owner’s value is also destroyed when the owner’s scope ends

I’m not going to go into all the details of these three things, but I want to keep them in mind, and we’ll talk about them later. At present, what we need to know is why Rust has ownership mechanism and what specific problems it solves.

What problem does Ownership solve

Ownership mainly solves the management problem of data memory on the heap. For those of you who have experience in programming, you know that both strongly typed and weakly typed programming languages have simple data types, such as String, int, float, Boolean, and complex data types, such as struct, object, etc. Different data types occupy different areas of memory. For simple data types, in strongly typed languages, the amount of memory they can be declared with is fixed and known, and the data is stored in the stack area of memory. For complex data types, the amount of memory they occupy cannot be determined at compile time because their values change dynamically, and they are stored in memory using the heap area. A typical scenario is when you’re developing a command line application where you need to assign user input to a variable. Since user input is unpredictable, you can only determine how much memory the variable needs at run time.

Whether it is a simple type or a complex type, when its scope at the end of the internal will automatically call drop method to remove the rust of memory, but the question is if there are multiple variables refer to the same piece of memory area at the same time if the variables are destroyed, will lead to the same memory region is released many times, it will also lead to memory corruption, bring safe hidden trouble. Ownership is rust’s solution to this problem, so how is it reflected at the code level? Look at the breakdown below

Ownership code is embodied

Let’s start with a set of code and execution results demos:

  • Simple types:

    Execution Result:

  • Complex types:

    Execution Result:

The above two sets of code execute the same logic, but the results are completely different. In example 1, when the value of the x variable is bound to y, printing the values of x and Y will normally display the desired result. But in example 2, when the s1 value is bound to S2, rust reports an error at compile time when the s1 and S2 values are printed. Why? . Is there a difference in internal logic between simple types and complex types when assigning values via variables? Yes, there are huge differences, and I’ll illustrate them with a few diagrams. In the example, because variable x is a simple type, its value is stored on the stack. When assigning to variable Y, the process of value copying is actually performed. As a result, a new space is created on the stack to store the value of y, as shown in the following diagram:


In Example 2, String is a complex type (the concept of JS is not introduced here. In Rust, String is used to store dynamically changing strings and is a complex type). Copying the value of s1 to S2 is actually copying the pointer, as shown in the following diagram:

From S1 to S2, the Pointers point to the same memory space in the heap. In this case, when the scope of S1 and S2 ends and the variable needs to be destroyed to release the memory, the same memory area will be released for many times if it is not processed. To avoid this problem, Rust adopts the ownership mechanism. Reviewing the three generalizations mentioned earlier when we introduced ownership, for a value, there can only be one owner at a time. When s1 is assigned to S2, because the two owners refer to the same memory space, s1 is destroyed after the assignment, and S2 takes over ownership of the memory space. The result is that the variable s1 cannot be accessed as we saw in the execution result of the example 2 program. The schematic diagram is as follows:

In addition to explicit variable assignment, common function parameter transfer is also the scene of large-scale ownership handover. The sample code looks like this:

By pulling a more, this kind of pointer copying with js complex type of reference is similar, but the js reference does not like rust destroy when s1, but s1, s2 exist at the same time, and once the s2 value changed, the value of s1 will update it to js developers to track data changes at runtime bugs related increased the difficulty, This is why js has various immutable libraries.

conclusion

I believe that by now we have had a more intuitive understanding of rust Ownership mechanism. The core point of ownership is that only one owner can exist in a memory at the same time. When the scope of a variable ends, RUST will release the memory space occupied by the variable. Ownership also has a great impact on the way rust code is written. It may be difficult to adapt to at the beginning, but with more rust code written, it will eventually become handy. If you are interested in RUST, you are welcome to discuss with me.

Personal email: [email protected] Personal wechat: Longmaost