Skip to content

Commit c726497

Browse files
committed
c19 unsafe Rust features
1 parent f411d44 commit c726497

File tree

2 files changed

+141
-0
lines changed

2 files changed

+141
-0
lines changed

c19_unsafe/Cargo.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[package]
2+
name = "c19_unsafe"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7+
8+
[dependencies]

c19_unsafe/src/main.rs

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
//use core::slice;
2+
use std::slice;
3+
4+
5+
unsafe fn dangerous() {
6+
println!("Danger!");
7+
}
8+
9+
fn split_at_mut(values: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]){
10+
let len = values.len();
11+
let ptr = values.as_mut_ptr();
12+
13+
assert!(mid<=len);
14+
unsafe {
15+
(
16+
slice::from_raw_parts_mut(ptr, mid),
17+
slice::from_raw_parts_mut(ptr.add(mid), len-mid),
18+
)
19+
}
20+
//(&mut values[..mid], &mut values[mid..])
21+
}
22+
23+
/*
24+
- "C" defines ABI the external function uses.
25+
- ABI defines how to call the function at the assembly level.
26+
- The "C" ABI is the most common and follows the C programming language's ABI.
27+
*/
28+
extern "C" {
29+
// names and signatures of external functions from C
30+
fn abs(input: i32) -> i32;
31+
}
32+
33+
34+
#[no_mangle]
35+
pub extern "C" fn call_from_c() {
36+
println!("Output from a Rust function! Callable by C.");
37+
}
38+
39+
// immutable global static variable
40+
static HELLO_WORLD: &str = "Hello world!";
41+
42+
// mutable global static variable
43+
static mut COUNTER: u32 = 0;
44+
fn add_to_count(inc: u32) {
45+
// mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
46+
// so must be within unsafe block.
47+
unsafe {
48+
COUNTER += inc;
49+
}
50+
}
51+
52+
//unsafe traits
53+
unsafe trait Foo {
54+
// methods
55+
}
56+
57+
unsafe impl Foo for i32 {
58+
//
59+
}
60+
61+
fn main() {
62+
println!("1) Dereference two raw pointers that point to the same data, output after changing value for one of them.");
63+
let mut num = 5;
64+
65+
let r1 = &num as *const i32;
66+
let r2 = &mut num as *mut i32;
67+
68+
// a random address in memory
69+
let address = 0x012345usize;
70+
let r = address as *mut i32;
71+
72+
unsafe {
73+
//can change r2 but not r1 because r1 is const raw pointer.
74+
*r2 += 1;
75+
println!("r1 is: {}", *r1);
76+
println!("r2 is: {}", *r2);
77+
// accessing this random address results in segmentation fault
78+
//println!("r is: {}", *r);
79+
}
80+
81+
println!("2) Obtain 10K elements at address {address} results in segmentation fault");
82+
let values= unsafe {
83+
// appending ; results in returning unit (empty structure)
84+
// removing ; will incur segmentation fault as it tries to access a random address.
85+
slice::from_raw_parts_mut(r, 10000);
86+
};
87+
println!("10K elements (fake obtaining. true obtaining results in segmentation fault) are {:?}", values);
88+
89+
println!("3) Call an unsafe function");
90+
unsafe {
91+
dangerous();
92+
}
93+
94+
println!("4) Create a safe abstraction over unsafe code");
95+
96+
let mut v = vec![1,2,3,4,5,6];
97+
let r = &mut v[..];
98+
let (a,b) = r.split_at_mut(3);
99+
100+
println!("First 3 elements are {:?}", a);
101+
println!("Elements after first 3 elements are {:?}", b);
102+
assert_eq!(a, &mut [1,2,3]);
103+
assert_eq!(b, &mut [4,5,6]);
104+
105+
println!("4.1) Safely call own split_at_mut() that contains an unsafe block");
106+
107+
let (a,b) = split_at_mut(&mut v, 3);
108+
println!("First 3 elements are {:?}", a);
109+
println!("Elements after first 3 elements are {:?}", b);
110+
assert_eq!(a, &mut [1,2,3]);
111+
assert_eq!(b, &mut [4,5,6]);
112+
113+
println!("5) Use extern functions to call external code");
114+
unsafe {
115+
println!("Absolute value of -3 according to C is {}", abs(-3));
116+
}
117+
118+
println!("6) Accessing or changing a global or static variable");
119+
println!("name is {}", HELLO_WORLD);
120+
121+
unsafe {
122+
// mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
123+
// so must be within unsafe block.
124+
println!("Counter is {COUNTER}");
125+
}
126+
add_to_count(3);
127+
unsafe {
128+
// mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
129+
// so must be within unsafe block.
130+
println!("Counter after adding 3 is {COUNTER}");
131+
}
132+
133+
}

0 commit comments

Comments
 (0)