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

Techboy

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

ایمنی حافظه زنگ زدگی توضیح داد

چه چیزی زبان Rust را به یکی از بهترین ها برای نوشتن برنامه های سریع و ایمن برای حافظه تبدیل می کند؟ ویژگی‌های ایمنی Rust در خود زبان گنجانده شده است.

چه چیزی زبان Rust را به یکی از بهترین ها برای نوشتن برنامه های سریع و ایمن برای حافظه تبدیل می کند؟ ویژگی‌های ایمنی Rust در خود زبان گنجانده شده است.

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

زبان‌های دیگر، مانند C، ممکن است سریع و نزدیک به فلز اجرا شوند، اما فاقد ویژگی‌های زبانی برای اطمینان از تخصیص و دفع مناسب حافظه برنامه هستند. همانطور که اخیراً توسط دفتر مدیر ملی سایبری کاخ سفید اشاره شد، این کاستی‌ها ناامنی‌ها و سوء استفاده‌های نرم‌افزاری را با عواقب پرهزینه در دنیای واقعی فعال می‌کنند. زبان‌هایی مانند Rust که ایمنی حافظه را در اولویت قرار می‌دهند، توجه بیشتری را به خود جلب می‌کنند.

Rust چگونه ایمنی حافظه را به گونه‌ای که زبان‌های دیگر تضمین نمی‌کنند تضمین می‌کند؟ بیایید پیدا کنیم.

ایمنی حافظه زنگ زدگی: ویژگی زبان مادری

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

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

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

زبان‌های مدیریت‌شده با حافظه، مانند C#، Java، یا Python، توسعه‌دهنده را تقریباً از انجام هرگونه مدیریت دستی حافظه راحت می‌کنند. توسعه دهندگان می توانند روی نوشتن کد و انجام کارها تمرکز کنند. اما این راحتی هزینه دیگری دارد، معمولاً سرعت یا نیاز به زمان اجرا بیشتر. باینری‌های Rust می‌توانند بسیار فشرده باشند، به‌طور پیش‌فرض با سرعت اصلی ماشین اجرا شوند و از نظر حافظه ایمن بمانند.

هوش مصنوعی Netlify استقرارهای ناموفق را تجزیه و تحلیل می کند

متغیرهای زنگ: به طور پیش‌فرض غیرقابل تغییر

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

این ممکن است بی اهمیت به نظر برسد، اما تأثیر خالص آن این است که توسعه دهنده را وادار می کند تا از مقادیری که باید در یک برنامه قابل تغییر باشند و چه زمانی باید کاملاً آگاه باشد. استدلال کد به دست آمده آسانتر است زیرا به شما می گوید چه چیزی و کجا می تواند تغییر کند.

Immutable-by-default از مفهوم ثابت متمایز است. یک متغیر تغییرناپذیر را می‌توان محاسبه کرد و سپس در زمان اجرا به‌عنوان غیرقابل تغییر ذخیره کرد، یعنی می‌توان آن را محاسبه، ذخیره کرد و سپس تغییر نداد. با این حال، یک ثابت باید در زمان کامپایل، قبل از اجرای برنامه قابل محاسبه باشد. بسیاری از انواع مقادیر – برای مثال ورودی کاربر – نمی توانند به عنوان ثابت به این روش ذخیره شوند.

C++ برعکس Rust را فرض می کند: به طور پیش فرض، همه چیز قابل تغییر است. شما باید از کلمه کلیدی const استفاده کنید تا چیزها را تغییرناپذیر اعلام کنید. شما می‌توانید یک سبک کدنویسی C++ با استفاده از const به‌طور پیش‌فرض اتخاذ کنید، اما این فقط کدی را که شما می‌نویسید پوشش می‌دهد. Rust تضمین می‌کند که همه برنامه‌هایی که به زبان نوشته شده‌اند، اکنون و آینده، به‌طور پیش‌فرض تغییر ناپذیری را فرض می‌کنند.

مالکیت، استقراض، و مراجع در Rust

هر مقدار در Rust یک “مالک” دارد، به این معنی که تنها یک چیز در هر زمان، در هر نقطه از کد، می‌تواند کنترل کامل خواندن/نوشتن روی یک مقدار داشته باشد. مالکیت را می توان به طور موقت واگذار کرد یا “قرض گرفت”، اما این رفتار به شدت توسط کامپایلر Rust پیگیری می شود. هر کدی که قوانین مالکیت یک شی معین را نقض کند به سادگی کامپایل نمی شود.

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

چگونه حاکمیت داده باید برای مقابله با چالش هوش مصنوعی مولد تکامل یابد

طول عمر در زنگ

ارجاع به مقادیر در Rust فقط دارای مالک نیستند، بلکه طول عمر دارند – به معنای محدوده ای است که یک مرجع معین برای آن معتبر است. در اکثر کدهای Rust، طول عمر را می توان به صورت ضمنی رها کرد، زیرا کامپایلر آنها را ردیابی می کند. اما طول عمر را می توان به صراحت برای موارد استفاده پیچیده تر نیز توضیح داد. صرف نظر از این، تلاش برای دسترسی یا اصلاح چیزی خارج از طول عمر آن، یا پس از “خارج شدن از محدوده”، منجر به خطای کامپایلر می شود. این دوباره مانع از تولید کل اشکال خطرناک با کد Rust می شود.

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

با زبان های مدیریت شده مانند جاوا، سی شارپ یا پایتون، مدیریت حافظه مسئولیت زمان اجرا زبان است. این به قیمت نیاز به زمان اجرا قابل توجه است و گاهی اوقات سرعت اجرا را کاهش می دهد. Rust قوانین مادام العمر را قبل از اجرای کد اجرا می کند.

ایمنی حافظه Rust هزینه دارد

ایمنی حافظه Rust نیز هزینه هایی دارد. اولین و بزرگترین نیاز به یادگیری و استفاده از خود زبان است.

تغییر به یک زبان جدید هرگز آسان نیست، و یکی از انتقادات رایج به Rust، منحنی یادگیری اولیه آن است، حتی برای برنامه نویسان با تجربه. درک مدل مدیریت حافظه Rust به زمان و کار نیاز دارد. منحنی یادگیری Rust حتی در بین طرفداران این زبان یک نقطه بحث ثابت است.

نحوه استفاده از PyInstaller برای ایجاد فایل های اجرایی پایتون

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

گفته شد، در حدود یک دهه که Rust وجود داشته است، ابزار، مستندات و جامعه کاربری را به دست آورده است که سرعت گرفتن را آسان‌تر می‌کند. و مجموعه «جعبه‌های» شخص ثالث، یا کتابخانه‌های Rust، از قبل گسترده و روزانه در حال رشد است. استفاده از Rust ممکن است مستلزم یک دوره بازآموزی و ابزار مجدد باشد، اما کاربران به ندرت فاقد منابع یا پشتیبانی کتابخانه برای یک کار معین خواهند بود.

کاربرد درس های Rust در سایر زبان ها

رشد Rust باعث ایجاد مکالمات در مورد تغییر زبان‌های موجود که فاقد ایمنی حافظه برای استفاده از ویژگی‌های محافظت از حافظه Rust هستند، شده است.

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

هیچ یک از اینها مانع از تلاش افراد نشده است. پروژه‌های مختلف سعی کرده‌اند برنامه‌های افزودنی برای C یا C++ با قوانینی در مورد ایمنی و مالکیت حافظه ایجاد کنند. پروژه های کربن و Cppfront ایده هایی را در این زمینه بررسی می کنند. Carbon یک زبان کاملاً جدید با ابزارهای مهاجرت برای کدهای ++C موجود است و Cppfront یک نحو جایگزین برای C++ به عنوان راهی برای نوشتن ایمن‌تر و راحت‌تر پیشنهاد می‌کند. اما هر دوی این پروژه ها نمونه اولیه باقی می مانند. Cppfront فقط اولین نسخه کامل و کامل خود را در مارس ۲۰۲۴ منتشر کرد. p>

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