@@ -868,27 +868,108 @@ fn first((value, _): (int, float)) -> int { value }
868
868
869
869
# Destructors
870
870
871
- A * destructor * is a function responsible for cleaning up the resources used by
872
- an object when it is no longer accessible. Destructors can be defined to handle
873
- the release of resources like files, sockets and heap memory .
871
+ C-style resource management requires the programmer to match every allocation
872
+ with a free, which means manually tracking the responsibility for cleaning up
873
+ ( the owner). Correctness is left to the programmer, and it's easy to get wrong .
874
874
875
- Objects are never accessible after their destructor has been called, so there
876
- are no dynamic failures from accessing freed resources. When a task fails, the
877
- destructors of all objects in the task are called.
875
+ The following code demonstrates manual memory management, in order to contrast
876
+ it with Rust's resource management. Rust enforces safety, so the ` unsafe `
877
+ keyword is used to explicitly wrap the unsafe code. The keyword is a promise to
878
+ the compiler that unsafety does not leak outside of the unsafe block, and is
879
+ used to create safe concepts on top of low-level code.
878
880
879
- The ` ~ ` sigil represents a unique handle for a memory allocation on the heap:
881
+ ~~~~
882
+ use core::libc::{calloc, free, size_t};
883
+
884
+ fn main() {
885
+ unsafe {
886
+ let a = calloc(1, int::bytes as size_t);
887
+
888
+ let d;
880
889
890
+ {
891
+ let b = calloc(1, int::bytes as size_t);
892
+
893
+ let c = calloc(1, int::bytes as size_t);
894
+ d = c; // move ownership to d
895
+
896
+ free(b);
897
+ }
898
+
899
+ free(d);
900
+ free(a);
901
+ }
902
+ }
881
903
~~~~
882
- {
883
- // an integer allocated on the heap
884
- let y = ~10;
904
+
905
+ Rust uses destructors to handle the release of resources like memory
906
+ allocations, files and sockets. An object will only be destroyed when there is
907
+ no longer any way to access it, which prevents dynamic failures from an attempt
908
+ to use a freed resource. When a task fails, the stack unwinds and the
909
+ destructors of all objects owned by that task are called.
910
+
911
+ The unsafe code from above can be contained behind a safe API that prevents
912
+ memory leaks or use-after-free:
913
+
914
+ ~~~~
915
+ use core::libc::{calloc, free, c_void, size_t};
916
+
917
+ struct Blob { priv ptr: *c_void }
918
+
919
+ impl Blob {
920
+ fn new() -> Blob {
921
+ unsafe { Blob{ptr: calloc(1, int::bytes as size_t)} }
922
+ }
923
+ }
924
+
925
+ impl Drop for Blob {
926
+ fn finalize(&self) {
927
+ unsafe { free(self.ptr); }
928
+ }
929
+ }
930
+
931
+ fn main() {
932
+ let a = Blob::new();
933
+
934
+ let d;
935
+
936
+ {
937
+ let b = Blob::new();
938
+
939
+ let c = Blob::new();
940
+ d = c; // move ownership to d
941
+
942
+ // b is destroyed here
943
+ }
944
+
945
+ // d is destroyed here
946
+ // a is destroyed here
885
947
}
886
- // the destructor frees the heap memory as soon as `y` goes out of scope
887
948
~~~~
888
949
889
- Rust includes syntax for heap memory allocation in the language since it's
890
- commonly used, but the same semantics can be implemented by a type with a
891
- custom destructor.
950
+ This pattern is common enough that Rust includes dynamically allocated memory
951
+ as first-class types (` ~ ` and ` @ ` ). Non-memory resources like files are cleaned
952
+ up with custom destructors.
953
+
954
+ ~~~~
955
+ fn main() {
956
+ let a = ~0;
957
+
958
+ let d;
959
+
960
+ {
961
+ let b = ~0;
962
+
963
+ let c = ~0;
964
+ d = c; // move ownership to d
965
+
966
+ // b is destroyed here
967
+ }
968
+
969
+ // d is destroyed here
970
+ // a is destroyed here
971
+ }
972
+ ~~~~
892
973
893
974
# Ownership
894
975
@@ -903,22 +984,6 @@ and destroy the contained object when they go out of scope. A box managed by
903
984
the garbage collector starts a new ownership tree, and the destructor is called
904
985
when it is collected.
905
986
906
- ~~~~
907
- // the struct owns the objects contained in the `x` and `y` fields
908
- struct Foo { x: int, y: ~int }
909
-
910
- {
911
- // `a` is the owner of the struct, and thus the owner of the struct's fields
912
- let a = Foo { x: 5, y: ~10 };
913
- }
914
- // when `a` goes out of scope, the destructor for the `~int` in the struct's
915
- // field is called
916
-
917
- // `b` is mutable, and the mutability is inherited by the objects it owns
918
- let mut b = Foo { x: 5, y: ~10 };
919
- b.x = 10;
920
- ~~~~
921
-
922
987
If an object doesn't contain garbage-collected boxes, it consists of a single
923
988
ownership tree and is given the ` Owned ` trait which allows it to be sent
924
989
between tasks. Custom destructors can only be implemented directly on types
@@ -942,7 +1007,7 @@ refer to that through a pointer.
942
1007
## Owned boxes
943
1008
944
1009
An owned box (` ~ ` ) is a uniquely owned allocation on the heap. It inherits the
945
- mutability and lifetime of the owner as it would if there was no box:
1010
+ mutability and lifetime of the owner as it would if there was no box.
946
1011
947
1012
~~~~
948
1013
let x = 5; // immutable
@@ -956,8 +1021,8 @@ let mut y = ~5; // mutable
956
1021
957
1022
The purpose of an owned box is to add a layer of indirection in order to create
958
1023
recursive data structures or cheaply pass around an object larger than a
959
- pointer. Since an owned box has a unique owner, it can only be used to
960
- represent a tree data structure.
1024
+ pointer. Since an owned box has a unique owner, it can be used to represent any
1025
+ tree data structure.
961
1026
962
1027
The following struct won't compile, because the lack of indirection would mean
963
1028
it has an infinite size:
@@ -1027,6 +1092,7 @@ d = b; // box type is the same, okay
1027
1092
c = b; // error
1028
1093
~~~~
1029
1094
1095
+
1030
1096
# Move semantics
1031
1097
1032
1098
Rust uses a shallow copy for parameter passing, assignment and returning values
0 commit comments