|
| 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 |
0 commit comments