۳۰ شهریور ۱۴۰۳

Techboy

اخبار و اطلاعات روز تکنولوژی

۶ اشتباه برنامه نویسی Rust که باید مراقب آنها باشید

زبان برنامه نویسی ایمن مورد علاقه همه افراد دارای مشکلاتی است. در اینجا شش اشتباه وجود دارد که باید هنگام نوشتن کد Rust مراقب آنها باشید.

زبان برنامه نویسی ایمن مورد علاقه همه افراد دارای مشکلاتی است. در اینجا شش اشتباه وجود دارد که باید هنگام نوشتن کد Rust مراقب آنها باشید.

Rust راهی به برنامه نویسان ارائه می دهد تا نرم افزار ایمن حافظه را بدون جمع آوری زباله بنویسند که با سرعت اصلی ماشین اجرا می شود. همچنین یک زبان پیچیده برای تسلط، با منحنی یادگیری اولیه نسبتاً شیب دار است. در اینجا پنج گچ‌چا، اسناگ و تله وجود دارد که باید در هنگام استفاده از Rust مراقب آنها باشید—و همچنین برای توسعه‌دهندگان باتجربه Rust.

Rust gotchas: 6 چیزی که باید در مورد نوشتن کد Rust بدانید

  • نمی‌توانید چک‌کننده قرض را «خاموش کنید»
  • از “_” برای متغیرهایی که می خواهید متصل کنید استفاده نکنید
  • بسته‌ها قوانین مادام العمر مشابه عملکردها را ندارند
  • همیشه وقتی وام منقضی می‌شود، تخریب‌کنندگان اجرا نمی‌شوند
  • مراقب چیزهای ناامن و عمر نامحدود باشید
  • .unwrap() کنترل رسیدگی به خطا را تسلیم می کند

شما نمی توانید بررسی کننده قرض را “خاموش” کنید

مالکیت، استقراض و طول عمر در Rust گنجانده شده است. آنها بخشی جدایی ناپذیر از نحوه حفظ ایمنی حافظه بدون جمع‌آوری زباله توسط زبان هستند.

برخی از زبان‌های دیگر ابزارهای بررسی کد را ارائه می‌کنند که به توسعه‌دهنده در مورد مشکلات ایمنی یا حافظه هشدار می‌دهند، اما همچنان اجازه می‌دهند کد کامپایل شود. زنگ به این صورت کار نمی کند. بررسی کننده قرض—بخشی از کامپایلر Rust که همه عملیات مالکیت معتبر هستند—یک ابزار اختیاری نیست که بتوان آن را خاموش کرد. کدی که برای چک کننده قرض معتبر نیست، کامپایل نمی شود، نقطه.

یک مقاله کامل می‌تواند نوشته شود (و شاید باید نوشته شود) در مورد اینکه چگونه با جستجوگر وام مبارزه نکنیم. ارزش آن را دارد که بخش Rust by Example در زمینه محدوده‌بندی را مرور کنید. چگونه قوانین برای بسیاری از رفتارهای رایج کار می کنند.

در مراحل اولیه سفر Rust خود، به یاد داشته باشید که همیشه می‌توانید با کپی کردن با .clone()، مشکلات مالکیت را حل کنید. برای بخش هایی از برنامه که پرفورمنس نیستند، ساختن کپی به ندرت تأثیر قابل اندازه گیری خواهد داشت. سپس، می‌توانید روی قسمت‌هایی تمرکز کنید که انجام می‌دهند به حداکثر کارایی کپی صفر نیاز دارند و نحوه کارآمدتر کردن قرض‌گیری و طول عمر خود را در آن بخش‌های برنامه بیابید.

جدیدترین Apple Xcode IDE تکمیل کد را بهبود می بخشد

از ‘_’ برای متغیرهایی که می خواهید متصل کنید استفاده نکنید

نام متغیر _ – یک زیرخط – رفتار خاصی در Rust دارد. به این معنی است که مقدار دریافت شده در متغیر به آن محدود نمی شود. معمولاً برای دریافت مقادیری که باید فوراً دور ریخته شوند استفاده می شود. برای مثال، اگر چیزی یک اخطار must_use صادر کند، اختصاص دادن آن به _ یک روش معمولی برای خاموش کردن این هشدار است.

برای این منظور، از زیرخط برای هیچ مقداری که فراتر از عبارتی که در آن استفاده شده است استفاده نکنید. توجه داشته باشید که ما در اینجا در مورد گزاره صحبت می کنیم، نه scope em>.

سناریوهایی که باید مراقب آن‌ها باشید، سناریوهایی هستند که می‌خواهید چیزی را تا زمانی که از محدوده خارج نشود، نگه دارید. اگر بلوک کدی مانند

دارید


let _ = String::from("  Hello World  ").trim();

رشته ایجاد شده بلافاصله پس از آن عبارت از محدوده خارج می‌شود—تا پایان بلوک حفظ نخواهد شد. ( فراخوانی روش برای اطمینان از حذف نشدن نتایج در کامپایل است.)

راه آسان برای جلوگیری از این مشکل این است که فقط از نام‌هایی مانند _user یا _item برای تکالیفی استفاده کنید که می‌خواهید تا انتها ادامه داشته باشید. از دامنه استفاده کنید، اما قصد ندارید برای چیزهای دیگر استفاده کنید.

بسته‌ها قوانین مادام العمر مشابه عملکردها را ندارند

این تابع را در نظر بگیرید:

fn function(x: &i32) -> &i32 {
    x
}

شما ممکن است سعی کنید این تابع را به عنوان یک بسته، برای مقدار بازگشتی از یک تابع بیان کنید:


fn main() {
    let closure = |x: &i32| x;
}

تنها مشکل این است که کار نمی کند. کامپایلر با این خطا به صدا در می آید: ممکن است طول عمر به اندازه کافی طولانی نباشد، زیرا ورودی و خروجی بسته شدن طول عمر متفاوتی دارند.

ساختن برای لینوکس و اندروید در ویندوز

یک راه برای دور زدن این موضوع استفاده از یک مرجع ثابت است:


fn main() {
    let _closure: &dyn Fn(&i32) -> &i32 = &|x: &i32| x;
}

استفاده از یک تابع جداگانه پرمخاطب تر است اما از این نوع مسائل جلوگیری می کند. این باعث می‌شود دامنه‌ها به صورت بصری واضح‌تر و آسان‌تر تجزیه شوند.

توجه: نمونه‌های این بخش از همیشه وقتی وام منقضی می‌شود، تخریب‌کنندگان اجرا نمی‌شوند

مانند C++، Rust به شما اجازه می‌دهد تا برای انواع مخرب‌ها ایجاد کنید، که می‌توانند زمانی که یک شی از محدوده خارج می‌شود، اجرا شوند. اما این بدان معنا نیست که اجرای آنها ضمانت شده است.

این نیز برای زمانی که یک وام بر روی یک شی معین منقضی می‌شود، شاید دو برابر نیز صادق باشد. اگر وام در مورد چیزی منقضی شود، این بدان معنا نیست که تخریب کننده آن قبلا اجرا شده است. در واقع، مواقعی وجود دارد که نمی‌خواهید تخریب‌کننده اجرا شود، فقط به این دلیل که اعتبار وام منقضی شده است – به عنوان مثال، زمانی که نشانگر چیزی را نگه می‌دارید.

اسناد Rust دارای دستورالعمل‌هایی برای اطمینان از اجرای یک تخریب‌گر است، و برای دانستن زمان اجرای تضمینی یک تخریبگر.

مراقب چیزهای ناامن و عمر نامحدود باشید

کلمه کلیدی ناامن برای برچسب گذاری روی کد Rust وجود دارد که می تواند کارهایی مانند عدم ارجاع اشاره گرهای خام را انجام دهد. این کاری است که نیازی نیست اغلب در Rust انجام دهید (امیدواریم!)، اما وقتی انجام می دهید، اکنون دنیای جدیدی از مشکلات احتمالی دارید.

به عنوان مثال، عدم ارجاع به یک اشاره گر خام تولید شده توسط یک عملیات ناامن منجر به عمر نامحدود. Rustonomicon، کتابی در مورد زنگ ناامن، هشدار می دهد که یک عمر نامحدود “به اندازه ای که زمینه ایجاب می کند بزرگ می شود.” این بدان معناست که می تواند به طور غیرمنتظره ای فراتر از آنچه در ابتدا به آن نیاز داشتید یا در نظر داشتید رشد کند.

معماری های بدون سر و سیستم های ترکیب پذیر چیست؟

اگر در مورد کاری که با یک مرجع نامحدود انجام می دهید دقیق هستید، نباید مشکلی داشته باشید. اما برای ایمنی، بهتر است نشانگرهای ارجاع‌نشده را در یک تابع قرار دهید و از طول عمر در مرز تابع استفاده کنید، نه اینکه اجازه دهید آنها در محدوده یک تابع بچرخند.

.unwrap() کنترل رسیدگی به خطا را تسلیم می کند

هرگاه عملیاتی نتیجه را برمی گرداند، دو روش اساسی برای مدیریت آن وجود دارد. یکی با .unwrap() یا یکی از پسرعموهای آن (مانند .unwrap_or()) است. دیگری با یک عبارت match تمام عیار برای رسیدگی به نتیجه Er است.

مزیت بزرگ

.unwrap() این است که راحت است. اگر در مسیر کدی هستید که هرگز انتظار ندارید شرایط خطایی ایجاد شود، یا به هر حال مقابله با یک شرط خطا غیرممکن است، می‌توانید از .unwrap() برای دریافت استفاده کنید. ارزشی که نیاز دارید و به کسب و کار خود ادامه دهید.

همه اینها هزینه دارد: هر شرایط خطا باعث ایجاد هراس و برنامه را متوقف کنید. وحشت در Rust به دلایلی غیرقابل بازیابی است: آنها نشانه ای از اشتباه بودن چیزی هستند که نشان دهنده وجود یک اشکال واقعی در برنامه است.

اگر از .unwrap() یا یکی از انواع .unwrap() مانند .unwrap_or() استفاده می کنید، آگاه باشید که هنوز ظرفیت رسیدگی به خطاها محدود است. شما باید مقداری را ارسال کنید که مطابق با نوع مقدار OK باشد. با match، انعطاف پذیری رفتاری بسیار بیشتری نسبت به ارائه چیزی از نوع مناسب دارید.

اگر فکر نمی‌کنید که هرگز در یک مسیر برنامه به آن انعطاف‌پذیری نیاز نخواهید داشت، .unwrap() اشکالی ندارد. با این حال، همچنان توصیه می‌شود ابتدا یک تطابق کامل بنویسید تا ببینید آیا برخی از جنبه‌های مدیریت را نادیده گرفته‌اید.