@@ -868,108 +868,27 @@ fn first((value, _): (int, float)) -> int { value }
868
868
869
869
# Destructors
870
870
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 .
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 .
874
874
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.
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.
880
878
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;
879
+ The ` ~ ` sigil represents a unique handle for a memory allocation on the heap:
889
880
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
- }
903
881
~~~~
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
882
+ {
883
+ // an integer allocated on the heap
884
+ let y = ~10;
947
885
}
886
+ // the destructor frees the heap memory as soon as `y` goes out of scope
948
887
~~~~
949
888
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
- ~~~~
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.
973
892
974
893
# Ownership
975
894
@@ -984,6 +903,22 @@ and destroy the contained object when they go out of scope. A box managed by
984
903
the garbage collector starts a new ownership tree, and the destructor is called
985
904
when it is collected.
986
905
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
+
987
922
If an object doesn't contain garbage-collected boxes, it consists of a single
988
923
ownership tree and is given the ` Owned ` trait which allows it to be sent
989
924
between tasks. Custom destructors can only be implemented directly on types
@@ -1007,7 +942,7 @@ refer to that through a pointer.
1007
942
## Owned boxes
1008
943
1009
944
An owned box (` ~ ` ) is a uniquely owned allocation on the heap. It inherits the
1010
- mutability and lifetime of the owner as it would if there was no box.
945
+ mutability and lifetime of the owner as it would if there was no box:
1011
946
1012
947
~~~~
1013
948
let x = 5; // immutable
@@ -1021,8 +956,8 @@ let mut y = ~5; // mutable
1021
956
1022
957
The purpose of an owned box is to add a layer of indirection in order to create
1023
958
recursive data structures or cheaply pass around an object larger than a
1024
- pointer. Since an owned box has a unique owner, it can be used to represent any
1025
- tree data structure.
959
+ pointer. Since an owned box has a unique owner, it can only be used to
960
+ represent a tree data structure.
1026
961
1027
962
The following struct won't compile, because the lack of indirection would mean
1028
963
it has an infinite size:
@@ -1092,7 +1027,6 @@ d = b; // box type is the same, okay
1092
1027
c = b; // error
1093
1028
~~~~
1094
1029
1095
-
1096
1030
# Move semantics
1097
1031
1098
1032
Rust uses a shallow copy for parameter passing, assignment and returning values
0 commit comments