Skip to content

Commit 7b7085d

Browse files
committed
Initiated a new sample about unsafe coding
1 parent 10b3fa7 commit 7b7085d

6 files changed

Lines changed: 156 additions & 1 deletion

File tree

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,4 @@ members = [
2828
, "S23_asynchronous_programming"
2929
, "S24_file_io"
3030
, "S25_streams"
31-
]
31+
, "S26_unsafe_coding"]

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ bakabilirsiniz. Buradaki kodlar anlatımları desteklemek amacıyla kullanılır
3737
- [x] S23 - Asynchronous Programming
3838
- [x] S24 - File I/O Operations
3939
- [x] S25 - Stream Operations
40+
- [ ] S26 - Unsafe Zone
4041

4142
## Yardımcılar
4243

S26_unsafe_coding/Cargo.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[package]
2+
name = "S26_unsafe_coding"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]

S26_unsafe_coding/src/advanced.rs

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
Aynı türden nesneleri çok sık oluşturup(create) kaldırdığımız(drop) bir durum olduğunu ve bunu
3+
kısıtlı bellek kapasitesine sahip bir gömülü sistem üzerinde işletmemiz gerektiğini düşünelim.
4+
Böyle bir durumda kendi bellek havuzumu oluşturup yönetebiliriz ama bunun için unsafe alana
5+
çıkmamız gerekir. Aşağıdaki kodlarda bu kullanima ait bir örnek yer alıyor.
6+
7+
Olası hataları ise şöyle ifade edebiliriz.
8+
9+
User After Free: Serbest kalan bellek bloğuna erişmeye çalışmak
10+
Double Free : Aynı bellek bloğunu birden fazla kez serbest bırakılmaya çalışılması
11+
*/
12+
use std::alloc::{alloc, dealloc, Layout};
13+
use std::ptr;
14+
15+
// const X64_ALIGN: usize = 8;
16+
17+
/*
18+
Sistemin 32 veya 64 bit olmasına göre gerekli olan byte hizalama değerini aldığımı fonksiyon
19+
*/
20+
fn get_alignment() -> usize {
21+
if cfg!(target_pointer_width = "32") {
22+
4 // 32-bit alignment
23+
} else {
24+
8 // 64-bit alignment
25+
}
26+
}
27+
28+
struct RapidMemoryPool {
29+
total_size: usize,
30+
usage: usize,
31+
ref_pointer: *mut u8, //raw memory pointer
32+
}
33+
34+
impl RapidMemoryPool {
35+
fn new(total_size: usize) -> Self {
36+
println!("Rapid Memory Pool initiating");
37+
38+
unsafe {
39+
let layout = Layout::from_size_align(total_size, get_alignment()).unwrap();
40+
println!("{layout:?}");
41+
let ref_pointer = alloc(layout);
42+
if ref_pointer.is_null() {
43+
panic!("Could not allocate memory");
44+
}
45+
Self {
46+
total_size,
47+
usage: 0,
48+
ref_pointer,
49+
}
50+
}
51+
}
52+
53+
/*
54+
Bu fonksiyon bir bellek bölgesini ayırır ve başlangıç adresini
55+
raw pointer olarak döner. Buradaki raw pointer mutable'dır.
56+
*/
57+
fn allocate(&mut self, amount: usize) -> *mut u8 {
58+
unsafe {
59+
if self.usage + amount > self.total_size {
60+
panic!("Out of memory");
61+
}
62+
let alloc_ptr = self.ref_pointer.add(self.usage);
63+
self.usage += amount;
64+
alloc_ptr
65+
}
66+
}
67+
68+
fn free(&mut self) {
69+
unsafe {
70+
let layout = Layout::from_size_align(self.total_size, get_alignment()).unwrap();
71+
dealloc(self.ref_pointer, layout);
72+
self.ref_pointer = ptr::null_mut();
73+
self.total_size = 0;
74+
self.usage = 0;
75+
}
76+
}
77+
}
78+
79+
impl Drop for RapidMemoryPool {
80+
fn drop(&mut self) {
81+
if !self.ref_pointer.is_null() {
82+
self.free();
83+
println!("Dropping memory pool");
84+
}
85+
}
86+
}
87+
88+
pub fn run() {
89+
let mut pool = RapidMemoryPool::new(1024);
90+
91+
unsafe {
92+
let block_red = pool.allocate(256); // 256 byte yer ayırır
93+
println!("Block Red allocated at: {:?}", block_red);
94+
95+
let block_blue = pool.allocate(512); // 512 byte yer ayırır
96+
println!("Block Blue allocated at: {:?}", block_blue);
97+
}
98+
} // Drop trait implementasyonu nedeniyle buradan bellek otomatik serbest kalır

S26_unsafe_coding/src/main.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
Rust, bellek güvenliğini sağlama ve eşzamanlılık garantilerini sunmak üzere tasarlanmış bir
3+
bellek yönetim sistemini benimser. Ancak bazı hallerde bu güvenli alanın dışına çıkılması
4+
gerekebilir. Bu genellikle unsafe kod blokları ile gerçekleştirilir.
5+
6+
Unsafe bloklarda dilin standart güvnelik mekanizmaları göz ardı edilir. Unsafe kod tarafına
7+
çıkmayı gerektiren durumlar kısaca şöyle özetlenebilir.
8+
9+
- Performans iyileştirmeleri: Rust'un kontrol mekanizmaları performans üzerinde yük oluşturabilir.
10+
Mesela raw pointer'lar ile çalışmak çok hızlıdır. Bellek erişiminde bu hızlara çıkmak istediğimiz
11+
durumlarda ele alabiliriz.
12+
- C/C++ gibi rust dışındaki dillerle FFI(Foreign Function Interface) etkileşim kurmak istediğimiz
13+
hallerde tercih edilir.
14+
- Bellek bloklarını doğrudan manupile etmek istediğimiz hallerde.
15+
- Rust'ın normal veri yapılarından daha büyük boyutlardaki (union yapılar gerektiren haller)
16+
ihtiyaçlarda bit seviyesinde işlemler gerektiğinde
17+
- Yazılan kodun mantıksal olarak güvenli olduğu hallerde kullanılan built-in fonksiyonellikleri
18+
sağlayan api'ler için güvenlik kontrollerini atlamak istediğimizde
19+
20+
Unsafe kod kullanımında sorumluluk daha çok geliştiriciye kalır. Diğer yandan unsafe kod blokları
21+
gerekli olduğu yerlerde kullanılır ve kalan kod parçaları rust'ın güvenlik kriterlerine tabi
22+
olmaya devam eder.
23+
24+
Unsafe kodlama bellek güvenliği kriterlerinden feragat etmek anlamına gelse de, doğru şekilde
25+
ve yerlerde kullanıldığında sistem seviyesinde kontrol ve yüksek performans sağlar.
26+
*/
27+
mod advanced;
28+
mod simple_ffi;
29+
30+
fn main() {
31+
// simple_ffi::run();
32+
advanced::run();
33+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
Burada örnek bir FFI (Foreign Function Interface) kullanımı söz konusudur.
3+
Bu kullanımlarda unsafe kod blokları ele alınır.
4+
Örnekte Rust ortamından bir C fonksiyon çağrısı yapılır.
5+
*/
6+
extern "C" {
7+
fn strlen(s: *const i8) -> usize;
8+
}
9+
10+
pub fn run() {
11+
let c_string = std::ffi::CString::new("Rust programming language with Ferris").unwrap();
12+
let ptr = c_string.as_ptr();
13+
14+
unsafe {
15+
println!("String length: {}", strlen(ptr));
16+
}
17+
}

0 commit comments

Comments
 (0)