0Pricing
Learn Rust Coding · บทเรียน

การทำงานร่วมกับ Rust แบบไม่ปลอดภัย

ทำความเข้าใจเวลาและวิธีใช้บล็อก `unsafe` เพื่อข้ามการตรวจสอบความปลอดภัยของ Rust ทำให้ใช้ FFI และดำเนินการกับหน่วยความจำระดับต่ำได้

การทำงานร่วมกับ Rust แบบไม่ปลอดภัย เป็นบทเรียน Learn Rust Coding ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 3 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Learn Rust Coding และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Learn Rust Coding มีบทเรียนทั้งหมด 3 บทเรียน

Rust แบบไม่ปลอดภัย: บทนำ

ยินดีต้อนรับสู่Rust แบบไม่ปลอดภัย! แม้ Rust จะมีชื่อเสียงด้านการรับประกันความปลอดภัยของหน่วยความจำ แต่ก็มีบางสถานการณ์ที่คุณอาจจำเป็นต้องข้ามการตรวจสอบบางอย่าง

คีย์เวิร์ด unsafe ใน Rust ช่วยให้คุณทำเช่นนั้นได้ คีย์เวิร์ดนี้ไม่ได้มีไว้สำหรับเขียนโค้ดที่ "แย่" แต่เป็นเครื่องมือสำหรับกรณีการใช้งานขั้นสูงที่ต้องควบคุมหน่วยความจำหรือฮาร์ดแวร์โดยตรงมากขึ้น

พลังพิเศษห้าประการของโค้ดแบบไม่ปลอดภัย

เมื่อใช้บล็อก unsafe คุณจะเข้าถึงการดำเนินการพิเศษห้าประการที่โดยปกติคอมไพเลอร์ Rust จะป้องกันไว้:

  • ยกเลิกการอ้างอิงตัวชี้ดิบ: เข้าถึงที่อยู่หน่วยความจำโดยตรง
  • เรียกใช้ฟังก์ชันหรือเมธอด unsafe: เรียกใช้ฟังก์ชันที่มีเงื่อนไขก่อนการทำงานซึ่งคอมไพเลอร์ตรวจสอบไม่ได้
  • นำ trait unsafe ไปใช้: ประกาศว่าชนิดของคุณรักษาเงื่อนไขคงที่เฉพาะไว้
  • เข้าถึงหรือแก้ไขตัวแปรสแตติกแบบเปลี่ยนแปลงได้: แชร์สถานะที่เปลี่ยนแปลงได้ทั่วทั้งโปรแกรม ซึ่งเสี่ยงต่อการแข่งกันเข้าถึงข้อมูล
  • เข้าถึงฟิลด์ของ union: อ่านค่าจาก union ซึ่งอาจไม่ใช่ชนิดที่ถูกต้องสำหรับข้อมูลปัจจุบัน

การยกเลิกการอ้างอิงตัวชี้ดิบ

ตัวชี้ดิบ คือที่อยู่หน่วยความจำที่ไม่มีการรับประกันความปลอดภัยตามปกติของ Rust คุณสามารถสร้างตัวชี้เหล่านี้จากการอ้างอิง (&T, &mut T) ได้ แต่การยกเลิกการอ้างอิงต้องทำภายในบล็อก unsafe

นั่นหมายความว่า คุณในฐานะผู้เขียนโปรแกรมต้องรับผิดชอบในการตรวจสอบว่าตัวชี้ถูกต้องและชี้ไปยังหน่วยความจำที่จัดสรรไว้

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);
}

การเรียกใช้ฟังก์ชันแบบไม่ปลอดภัย

ฟังก์ชันบางรายการมีเครื่องหมายกำกับเป็น unsafe fn ซึ่งหมายความว่าฟังก์ชันนั้นมีเงื่อนไขก่อนการทำงานที่คอมไพเลอร์ Rust รับประกันไม่ได้ ตัวอย่างเช่น ฟังก์ชันอาจต้องการที่อยู่หน่วยความจำที่ถูกต้อง แต่ไม่สามารถตรวจสอบได้

การเรียกใช้ฟังก์ชันเหล่านี้ต้องครอบด้วยบล็อก unsafe เพื่อระบุว่าผู้เรียกเป็นผู้รับรองว่าเงื่อนไขก่อนการทำงานทั้งหมดเป็นจริง

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.");
}

ตัวแปรสแตติกแบบเปลี่ยนแปลงได้

โดยค่าเริ่มต้น Rust จะป้องกันสถานะส่วนกลางที่เปลี่ยนแปลงได้ เพื่อหลีกเลี่ยงการแข่งกันเข้าถึงข้อมูล อย่างไรก็ตาม คุณสามารถประกาศตัวแปรสแตติกแบบเปลี่ยนแปลงได้โดยใช้ static mut

การเข้าถึงหรือแก้ไขตัวแปรเหล่านี้ถือว่า unsafe เพราะหลายเธรดอาจพยายามเข้าถึงพร้อมกัน ซึ่งนำไปสู่พฤติกรรมที่ไม่กำหนดไว้ได้ การทำให้การเข้าถึงประสานกันอย่างถูกต้องเป็นความรับผิดชอบของคุณ

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);
  }
}

การนำ trait แบบไม่ปลอดภัยไปใช้

trait บางรายการใน Rust มีเครื่องหมายกำกับเป็น unsafe trait ซึ่งหมายความว่าการนำ trait เหล่านี้ไปใช้ต้องรักษาเงื่อนไขคงที่บางอย่างที่คอมไพเลอร์ตรวจสอบไม่ได้

ตัวอย่างทั่วไปคือ trait Send และ Sync ซึ่งเกี่ยวข้องกับความปลอดภัยของเธรด หากคุณนำ unsafe trait ไปใช้ด้วยตนเอง คุณต้องใช้ unsafe impl Trait for Type และรับประกันคุณสมบัติด้านความปลอดภัยของมัน

สำหรับผู้เริ่มต้นส่วนใหญ่ คุณจะพบกรณีนี้ไม่บ่อยนัก เพราะ Rust มักจัดการให้โดยอัตโนมัติหรือผ่านสิ่งห่อหุ้มที่ปลอดภัย

การเข้าถึงฟิลด์ของ Union

union คือชนิดพิเศษที่เก็บค่าของหนึ่งในตัวแปรรูปแบบได้ในแต่ละขณะ แต่ตัวแปรรูปแบบทั้งหมดใช้ตำแหน่งหน่วยความจำเดียวกัน แนวคิดนี้คล้าย union ในภาษา C

การเข้าถึงฟิลด์ของ union ต้องทำภายในบล็อก unsafe เพราะคอมไพเลอร์ไม่ทราบว่าฟิลด์ใดกำลังใช้งานอยู่ การอ่านฟิลด์ที่ไม่ได้ใช้งานอาจทำให้เกิดพฤติกรรมที่ไม่กำหนดไว้หรือตีความข้อมูลผิดได้

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);
  }
}

สถานการณ์การใช้โค้ดแบบไม่ปลอดภัยในทางปฏิบัติ

แม้ควรใช้ unsafe เท่าที่จำเป็น แต่ก็มีความสำคัญต่อการเขียนโปรแกรมขั้นสูงหลายประเภท:

  • อินเทอร์เฟซฟังก์ชันภายนอก (FFI): ติดต่อกับโค้ดที่เขียนด้วยภาษาอื่น เช่น ไลบรารี C หรือ C++
  • การปรับปรุงประสิทธิภาพ: ในบางกรณี การข้ามการตรวจสอบของ Rust อาจเพิ่มประสิทธิภาพได้เล็กน้อยในส่วนสำคัญ แต่ควรวัดผลก่อน
  • การเขียนโปรแกรมระบบระดับล่าง: เขียนระบบปฏิบัติการ ไดรเวอร์อุปกรณ์ หรือระบบฝังตัว
  • การสร้างสิ่งห่อหุ้มที่ปลอดภัย: สร้างโครงสร้างข้อมูลหรือ API ที่ปลอดภัยบนพื้นฐานขององค์ประกอบแบบไม่ปลอดภัย เช่น วิธีสร้าง Vec

ความรับผิดชอบของคุณเมื่อใช้โค้ดแบบไม่ปลอดภัย

เมื่อใช้ unsafe คุณต้องรับผิดชอบในการรักษาการรับประกันความปลอดภัยของ Rust ด้วยตนเอง ซึ่งหมายถึง:

  • ตรวจสอบว่าหน่วยความจำถูกต้องและจัดแนวอย่างเหมาะสม
  • ป้องกันการแข่งกันเข้าถึงข้อมูลเมื่อต้องจัดการกับสถานะที่แชร์และเปลี่ยนแปลงได้
  • หลีกเลี่ยงตัวชี้ที่ลอยอยู่หรือข้อผิดพลาดจากการใช้หน่วยความจำหลังคืนคืน
  • ตรวจสอบว่าเงื่อนไขก่อนการทำงานของฟังก์ชันทั้งหมดเป็นจริง

การใช้ unsafe ผิดวิธีอาจทำให้เกิดพฤติกรรมที่ไม่กำหนดไว้ ซึ่งเป็นข้อบกพร่องชนิดที่ร้ายแรงที่สุดและแก้ไขได้ยากมาก

ตรวจสอบความรู้เกี่ยวกับโค้ดแบบไม่ปลอดภัย

การดำเนินการใดต่อไปนี้จำเป็นต้องใช้บล็อก unsafe ใน Rust

ทบทวน: Rust แบบไม่ปลอดภัย

คุณได้เรียนรู้เกี่ยวกับRust แบบไม่ปลอดภัย ซึ่งเป็นความสามารถอันทรงพลังที่ช่วยให้คุณข้ามการตรวจสอบความปลอดภัยบางอย่างขณะคอมไพล์ของ Rust สำหรับสถานการณ์เฉพาะทางและขั้นสูง

โปรดจำไว้ว่า unsafe ไม่ได้ปิดตัวตรวจสอบการยืมทั้งหมด แต่จะโอนความรับผิดชอบด้านความปลอดภัยของหน่วยความจำและเงื่อนไขคงที่ทั้งหมดมาให้คุณในฐานะผู้เขียนโปรแกรม ใช้อย่างรอบคอบและระมัดระวังเป็นอย่างยิ่ง โดยทั่วไปใช้กับ FFI การปรับปรุงประสิทธิภาพระดับล่าง หรือการสร้างสิ่งห่อหุ้มที่ปลอดภัย

คำถามที่พบบ่อย

บทเรียน “การทำงานร่วมกับ Rust แบบไม่ปลอดภัย” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การทำงานร่วมกับ Rust แบบไม่ปลอดภัย” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Learn Rust Coding ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Learn Rust Coding มีบทเรียนทั้งหมด 3 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การทำงานร่วมกับ Rust แบบไม่ปลอดภัย”

ทำความเข้าใจเวลาและวิธีใช้บล็อก `unsafe` เพื่อข้ามการตรวจสอบความปลอดภัยของ Rust ทำให้ใช้ FFI และดำเนินการกับหน่วยความจำระดับต่ำได้ คุณปฏิบัติ Learn Rust Coding ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Learn Rust Coding หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Learn Rust Coding บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 3 บทเรียน

บทเรียน “การทำงานร่วมกับ Rust แบบไม่ปลอดภัย” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Learn Rust Coding นี้ได้ไหม

ได้ บทเรียน Learn Rust Coding ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. มาโครแบบประกาศ (`macro_rules!`)
  2. มาโครเชิงกระบวนการ: Derive, Function
  3. การทำงานร่วมกับ Rust แบบไม่ปลอดภัย
← กลับไปที่ Learn Rust Coding