0Pricing
Learn Rust Coding · درس

التعامل مع Rust غير الآمنة

افهموا متى وكيف تستخدمون كتل `unsafe` لتجاوز فحوصات الأمان في Rust، بما يتيح FFI وعمليات الذاكرة منخفضة المستوى.

التعامل مع Rust غير الآمنة درس مجاني في Learn Rust Coding على CoddyKit. هذا هو الدرس 3 من أصل 3. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Learn Rust Coding، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Learn Rust Coding 3 دروس في المجموع.

بعض أجزاء هذا الدرس لم تُترجم بعد وتظهر باللغة الإنجليزية.

Unsafe Rust: An Introduction

Welcome to Unsafe Rust! While Rust is famous for its memory safety guarantees, there are specific scenarios where you might need to bypass some of these checks.

The unsafe keyword in Rust allows you to do just that. It's not a way to write 'bad' code, but rather a tool for advanced use cases where you need more direct control over memory or hardware.

The Five Unsafe Superpowers

When you use an unsafe block, you gain access to five special actions that the Rust compiler normally prevents:

  • Dereference raw pointers: Directly access memory addresses.
  • Call unsafe functions or methods: Execute functions with preconditions the compiler can't verify.
  • Implement unsafe traits: Declare that your type upholds specific invariants.
  • Access or modify mutable static variables: Share mutable state globally, risking data races.
  • Access fields of unions: Read from a union, which might be an invalid type for the current data.

Dereferencing Raw Pointers

Raw pointers are memory addresses without Rust's usual safety guarantees. You can create them from references (&T, &mut T) but dereferencing them requires an unsafe block.

This means you, the programmer, are responsible for ensuring the pointer is valid and points to allocated memory.

fn main() {
  let mut num = 5;
  let r1 = &num as *const i32; // Immutable raw pointer
  let r2 = &mut num as *mut i32; // Mutable raw pointer

  unsafe { // The `unsafe` block starts here
    println!("r1 points to: {}", *r1);
    *r2 = 10; // Modify data through mutable raw pointer
    println!("r2 points to: {}", *r2);
  } // The `unsafe` block ends here

  println!("Num is now: {}", num);
}

Calling Unsafe Functions

Some functions are marked as unsafe fn. This means the function has preconditions that the Rust compiler cannot guarantee. For instance, a function might expect a valid memory address, but cannot verify it.

Calling such functions must be wrapped in an unsafe block, indicating that you, the caller, ensure all preconditions are met.

unsafe fn dangerous_operation() {
  println!("This operation could be dangerous if preconditions aren't met!");
}

fn main() {
  println!("Attempting a dangerous operation...");
  unsafe { // Calling an unsafe function requires `unsafe`
    dangerous_operation();
  }
  println!("Operation completed.");
}

Mutable Static Variables

Rust prevents global mutable state by default to avoid data races. However, you can declare mutable static variables using static mut.

Accessing or modifying these variables is considered unsafe because multiple threads could try to access them simultaneously, leading to undefined behavior. Proper synchronization is your responsibility.

static mut COUNTER: i32 = 0; // A mutable static variable

fn add_to_counter(inc: i32) {
  unsafe { // Modifying `static mut` requires `unsafe`
    COUNTER += inc;
  }
}

fn main() {
  add_to_counter(5);
  unsafe { // Reading `static mut` also requires `unsafe`
    println!("COUNTER after first add: {}", COUNTER);
  }

  add_to_counter(10);
  unsafe {
    println!("COUNTER after second add: {}", COUNTER);
  }
}

Implementing Unsafe Traits

Some traits in Rust are marked as unsafe trait. This signifies that implementing them requires upholding certain invariants that the compiler cannot check.

A common example is the Send and Sync traits, which relate to thread safety. If you manually implement an unsafe trait, you must use unsafe impl Trait for Type and guarantee its safety properties.

For most beginners, you'll encounter this less frequently, as Rust often handles these automatically or via safe abstractions.

Accessing Union Fields

A union is a special type that can hold a value of *one* of its variants at any given time, but all variants share the same memory location. It's similar to C unions.

Accessing a field of a union requires an unsafe block because the compiler cannot know which field is currently active. Reading from an inactive field can lead to undefined behavior or misinterpretation of data.

union Data {
  integer: u32,
  float: f32,
}

fn main() {
  let mut d = Data { integer: 42 }; // Initialize with an integer

  unsafe {
    // Accessing 'integer' is safe here
    println!("Integer value: {}", d.integer);

    // Accessing 'float' is unsafe, as 'integer' was initialized.
    // This would interpret the integer's bits as a float.
    // println!("Float value (unsafe): {}", d.float);
  }

  d.float = 3.14; // Now initialize with a float
  unsafe {
    // Accessing 'float' is safe now
    println!("Float value: {}", d.float);
  }
}

Practical Unsafe Scenarios

While unsafe should be used sparingly, it's crucial for several advanced programming tasks:

  • Foreign Function Interface (FFI): Interacting with code written in other languages (like C/C++ libraries).
  • Performance Optimizations: Sometimes, bypassing Rust's checks can yield small performance gains in critical sections (but measure first!).
  • Low-level System Programming: Writing operating systems, device drivers, or embedded systems.
  • Building Safe Abstractions: Implementing safe data structures or APIs on top of unsafe primitives (e.g., how Vec is built).

Your Responsibility with Unsafe

When you use unsafe, you take on the responsibility of upholding Rust's safety guarantees manually. This means:

  • Ensuring memory is valid and correctly aligned.
  • Preventing data races when dealing with shared mutable state.
  • Avoiding dangling pointers or use-after-free errors.
  • Ensuring all function preconditions are met.

Misusing unsafe can lead to undefined behavior, which is the worst kind of bug and can be very hard to debug.

Unsafe Knowledge Check

Which of the following actions requires an unsafe block in Rust?

Recap: Unsafe Rust

You've learned about Unsafe Rust, a powerful feature that allows you to bypass some of Rust's compile-time safety checks for specific, advanced scenarios.

Remember that unsafe doesn't turn off the borrow checker completely, but it shifts the responsibility for memory safety and invariants entirely to you, the programmer. Use it judiciously and with extreme caution, typically for FFI, low-level optimizations, or building safe abstractions.

الأسئلة الشائعة

هل درس «التعامل مع Rust غير الآمنة» مجاني؟

نعم — نص درس «التعامل مع Rust غير الآمنة» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Learn Rust Coding، انتقل إلى CoddyKit PRO. تتضمن دورة Learn Rust Coding 3 دروس في المجموع.

ماذا ستتعلم في «التعامل مع Rust غير الآمنة»؟

افهموا متى وكيف تستخدمون كتل `unsafe` لتجاوز فحوصات الأمان في Rust، بما يتيح FFI وعمليات الذاكرة منخفضة المستوى. تتمرن على Learn Rust Coding مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Learn Rust Coding؟

لا تُشترط خبرة سابقة. Learn Rust Coding على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 3.

كم من الوقت يستغرق درس «التعامل مع Rust غير الآمنة»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Learn Rust Coding هذا؟

نعم. كل درس في Learn Rust Coding يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. وحدات الماكرو التصريحية (`macro_rules!`)
  2. وحدات الماكرو الإجرائية: Derive وFunction
  3. التعامل مع Rust غير الآمنة
← العودة إلى Learn Rust Coding