গ্রেডন হোয়ার-এর ২০০৬ পরীক্ষার থেকে শুরু করে আজকের রাস্ট ইকোসিস্টেম পর্যন্ত—গারবেজ কালেক্টর ছাড়া মেমরি নিরাপত্তা কিভাবে সিস্টেম প্রোগ্রামিংয়ের প্রত্যাশা বদলে দিল তা দেখুন।

এই আর্টিকেলটি একটি কেন্দ্রীভূত উদ্ভব কাহিনি বলে: কিভাবে গ্রেডন হোয়ার-এর ব্যক্তিগত পরীক্ষা রাস্টে পরিণত হয়েছিল, এবং কেন রাস্টের ডিজাইন পছন্দগুলো সিস্টেম প্রোগ্রামিং সম্পর্কে প্রত্যাশা বদলে দিতে যথেষ্ট গুরুত্বপূর্ণ ছিল।
“সিস্টেম প্রোগ্রামিং” মেশিনের কাছাকাছি থাকে—এবং আপনার প্রডাক্টের ঝুঁকিরও কাছাকাছি। এটি ব্রাউজার, গেম ইঞ্জিন, অপারেটিং সিস্টেম কম্পোনেন্ট, ডেটাবেস, নেটওয়ার্কিং, এবং এমবেডেড সফটওয়্যারে দেখা যায়—এসব জায়গায় সাধারণত আপনি চান:
ঐতিহ্যগতভাবে, এই সম্মিলন দলগুলিকে C ও C++-এর দিকে নিয়ে যেত—সঙ্গে বিস্তর বিধি, রিভিউ, এবং টুলিং যাতে মেমরি-সংক্রান্ত বাগ কমে।
রাস্টের প্রধান প্রতিশ্রুতি বলা সহজ কিন্তু বাস্তবে ডেলিভার করা কঠিন:
গারবেজ কালেক্টর ছাড়া মেমরি নিরাপত্তা।
রাস্ট নির্দিষ্ট ভাবে use-after-free, double-free, এবং অনেক ধরনের ডাটা রেস প্রতিরোধ করতে চায়—কিন্তু একটি রানটাইম-ভিত্তিক GC-এ নির্ভর না করে। পরিবর্তে, রাস্ট মালিকানা এবং বোরোইংয়ের মাধ্যমে অনেক কাজ কম্পাইল টাইমে সরিয়ে দেয়।
আপনি ইতিহাস পাবেন (প্রাথমিক ধারনা থেকে Mozilla-র অন্তর্ভুক্তি পর্যন্ত) এবং মূল ধারণাগুলো (মালিকানা, বোরোইং, লাইফটাইম, safe বনাম unsafe) সহজ ভাষায় ব্যাখ্যা করা।
যা আপনি পাবেন না তা হলো সম্পূর্ণ রাস্ট টিউটোরিয়াল, সব সিনট্যাক্সের ট্যুর, বা ধাপে ধাপে প্রজেক্ট সেটআপ। এটিকে ধরা যেতে পারে রাস্ট ডিজাইনের “কেন” হিসেবে—পর্যাপ্ত উদাহরণসহ যাতে ধারণাগুলো স্পষ্ট হয়।
লেখকের নোট: পুরো পিসি লক্ষ্য ~৩,০০০ শব্দ—সংক্ষিপ্ত উদাহরণ রাখার জায়গা রেখে, কিন্তু রেফারেন্স ম্যানুয়াল হয়ে না যেতে।
রাস্ট কোনো কেমিটির নকশাধীন “পরবর্তী C++” হিসেবে শুরু করে নি। এটি ২০০৬ সালে গ্রেডন হোয়ার-এর একটি ব্যক্তিগত পরীক্ষায় শুরু হয়েছিল—প্রথমে তিনি স্বাধীনভাবে কাজ করেছিলেন, পরে এটি আরও বিস্তৃত মনোযোগ টুল। ওই উত্সটি গুরুত্বপূর্ণ: অনেক প্রাথমিক নকশা সিদ্ধান্তই প্রতিদিনের কষ্ট কমানোর প্রচেষ্টা হিসেবে পড়ে, ভাষা তত্ত্ব জিতে নেওয়ার চেষ্টা হিসেবে না।
হোয়ার ছিল ঠিক কীভাবে নিম্ন-স্তরের, উচ্চ-পারফরম্যান্স সফটওয়্যার লিখবেন যা গারবেজ কালেক্টরের উপর নির্ভর না করে—তার সাথেই C ও C++-এ ক্র্যাশ ও সিকিউরিটি বাগের সাধারণ কারণগুলোও এড়াতে চেয়েছিলেন। টেনশনটি সিস্টেম প্রোগ্রামারদের কাছে পরিচিত:
রাস্টের “GC ছাড়া মেমরি নিরাপত্তা” দিকটি প্রথমে মার্কেটিং ট্যাগলাইন ছিল না। এটি ছিল ডিজাইনের লক্ষ্য: সিস্টেম কাজে উপযুক্ত পারফরম্যান্স বজায় রেখে অনেক মেমরি বাগ প্রকাশ করা কঠিন করে তোলা।
প্রশ্ন করা যুক্তিযুক্ত: কেন এটা “শুধু C/C++-এর জন্য একটি ভালো কম্পাইলার” ছিল না? স্ট্যাটিক অ্যানালাইসিস, স্যানিটাইজার, এবং নিরাপদ লাইব্রেরি অনেক সমস্যা রোধ করে, কিন্তু সাধারণত তারা গ্যারান্টি দিতে পারে না। মূল ভাষাগুলো এমন প্যাটার্ন অনুমতি দেয় যেগুলো সম্পূর্ণরূপে বাইরের থেকে নিয়ন্ত্রন করা কঠিন বা অসম্ভব।
রাস্টের বাজি ছিল মূল নিয়মগুলো ভাষা ও টাইপ সিস্টেমে সরিয়ে দেওয়া যাতে নিরাপত্তা হয়ে ওঠে ডিফল্ট আউটকাম, আবার স্পষ্টভাবে চিহ্নিত এস্কেপ হ্যাচে ম্যানুয়াল কন্ট্রোল রাখে।
রাস্টের প্রাথমিক দিনগুলো সম্পর্কে কিছু বিবরণ বিস্তারিত ভ্রম হিসেবে ঘোরে (প্রায়ই টক ও ইন্টারভিউতে পুনরাবৃত্তি হয়)। এই উদ্ভব কাহিনি বলার সময়, ব্যাপকভাবে দলিলভিত্তিক মাইলফলকগুলো—যেমন ২০০৬ শুরু তারিখ এবং রাস্ট পরে Mozilla Research-এ গৃহীত হওয়া—কে ব্যক্তিগত স্মৃতি ও মাধ্যমিক পুনরবর্তনের থেকে আলাদা করা ভালো।
প্রাইমারি সোর্স হিসেবে খুঁজুন: প্রাথমিক রাস্ট ডকুমেন্টেশন ও ডিজাইন নোট, গ্রেডন হোয়ার-এর টক/ইন্টারভিউ, এবং Mozilla/Servo-যুগের পোস্টগুলো যা ব্যাখ্যা করে কেন প্রজেক্টটি নেওয়া হয়েছিল এবং কীভাবে লক্ষ্যগুলো ফ্রেম করা হয়েছিল। একটি ভালো “আরও পড়ুন” অংশ পাঠকদের ঐ অরিজিনালগুলোর দিকে ইঙ্গিত করতে পারে (দেখুন /blog সম্পর্কিত লিংকগুলো)।
সিস্টেম প্রোগ্রামিং প্রায়শই হার্ডওয়্যারের কাছাকাছি কাজ করা মানে। এই কাছাকাছি থাকা কোডকে দ্রুত ও রিসোর্স-কার্যকর করে—কিন্তু একই কারণে মেমরি ভুলগুলো এত কষ্টদায়ক।
কয়েকটি ক্লাসিক বাগ বারবার দেখা যায়:
এই ত্রুটিগুলো সবসময় স্পষ্ট নয়। একটি প্রোগ্রাম সপ্তাহ ধরে “চলতে” পারে, তারপর একটি বিরল টাইমিং বা ইনপুট প্যাটার্নে ক্র্যাশ করে।
টেস্টিং আপনি যে কেসগুলো চালিয়েছেন সেগুলো কাজ করে তা প্রমাণ করে। কিন্তু মেমরি বাগগুলো প্রায়ই সেই কেসগুলোতে লুকিয়ে থাকে যা আপনি করেননি: অদ্ভুত ইনপুট, ভিন্ন হার্ডওয়্যার, সূক্ষ্ম টাইমিং পরিবর্তন, বা নতুন কম্পাইলার সংস্করণ। এগুলো অ-নির্ধারিত হওয়াও সম্ভব—বিশেষ করে মাল্টি-থ্রেডেড প্রোগ্রামে—তাই বাগটি চলে যায় যখন আপনি লগ যোগ করেন বা ডিবাগার সংযুক্ত করেন।
মেমরি ভুল হলে আপনি শুধুমাত্র পরিষ্কার ত্রুটি পান না। রাজ্য দূষিত হয়, অনিয়মিত ক্র্যাশ হয়, এবং হামলাকারীরা যেসব দুর্বলতা খোঁজে সেগুলো তৈরী হয়। দলগুলি প্রচুর শক্তি ব্যয় করে এমন ব্যর্থতা ধরা ও নির্ণয় করতে—যেগুলো পুনরুত্পাদন করা কঠিন এবং আরও কঠিন ডায়াগনোজ করা যায়।
নিম্ন-স্তরের সফটওয়্যার সবসময় ভারি রানটাইম চেক বা ধারাবাহিক মেমরি স্ক্যানের দাম দিতে পারে না। লক্ষ্যটা হল—যেমন একটি ভাগ করা কর্মশালার টুল ধার করা: আপনি সেটি মুক্তভাবে ব্যবহার করতে পারেন, কিন্তু নিয়মগুলো স্পষ্ট হতে হবে—কে ধরে আছে, কে শেয়ার করতে পারে, এবং কখন তা ফিরিয়ে দিতে হবে। সিস্টেম ভাষাগুলো ঐ নিয়মগুলো মানব শৃঙ্খলার উপরে রেখে দেয়। রাস্টের গল্প শুরু হয় ঐ ট্রেডঅফকে প্রশ্ন করে।
গারবেজ কালেক্টর (GC) হলো ভাষাগুলোর একটি সাধারণ উপায় মেমরি বাগ প্রতিরোধ করার: রানটাইম ট্র্যাক করে কোন অবজেক্টগুলো প্রাপ্য এবং অবশিষ্টগুলো পুনরুদ্ধার করে দেয়। এতে use-after-free, double-free, এবং অনেক লিক ধরণ অদৃüşt হয়—কারণ প্রোগ্রাম সাধারণত “ভোলা” উপলব্ধি করে না একইভাবে।
GC নিজে “খারাপ” নয়, কিন্তু এটি প্রোগ্রামের পারফরম্যান্স প্রোফাইল বদলে দেয়। অধিকাংশ কালেক্টর কিছু মিলিয়ে দেয়:
অনেক অ্যাপ্লিকেশনের জন্য—ওয়েব ব্যাকএন্ড, ব্যবসায়িক সফটওয়্যার—এই খরচগুলো গ্রহণযোগ্য বা অদৃশ্য। আধুনিক GC চমৎকার এবং ডেভেলপারদের উৎপাদনশীলতা বাড়ায়।
সিস্টেম প্রোগ্রামিং-এ worst-case প্রায়ই সবচেয়ে গুরুত্বপূর্ণ। একটি ব্রাউজার ইঞ্জিনকে মসৃণ রেন্ডারিং দরকার; একটি এমবেডেড কন্ট্রোলারের কড়া টাইমিং বাধ্যতা থাকতে পারে; একটি নিম্ন-লেটেন্সি সার্ভার লোডের অধীনে টেইল লেটেন্সি শক্তভাবে ধরে রাখতে চায়। এই পরিবেশে “সাধারণত দ্রুত” এর চেয়ে “গড়ে পূর্বানুমেয়” বেশি মূল্যবান।
রাস্টের বড় প্রতিশ্রুতি ছিল: মেমরি ও ডেটা লেআউটের ওপর C/C++-সদৃশ নিয়ন্ত্রণ রাখুন, কিন্তু গারবেজ কালেক্টরের ওপর নির্ভর না করে মেমরি নিরাপত্তা প্রদান করুন। লক্ষ্য ছিল পূর্বানুমেয় পারফরম্যান্স ব্যাবহার—একই সঙ্গে নিরাপদ কোডকে ডিফল্ট করা।
এটি GC-কে নিম্নমান দাবি করা নয়। এটা বাজি ছিল যে একটি বড় ও গুরুত্বপূর্ণ মাঝামাঝি জমি আছে: সফটওয়্যার যা নিম্ন-স্তরের নিয়ন্ত্রণ এবং আধুনিক নিরাপত্তা চায়।
Ownership রাস্টের সহজ কিন্তু বড় ধারণা: প্রতিটি মানের একটি একক মালিক থাকে, যে সেটি আর প্রয়োজন নেই বুঝলে পরিষ্কার করে ফেলে।
এই এক নিয়ম অনেক ম্যানুয়াল “কে এই মেমরিটি ফ্রি করবে?”-র হিসাব বদলে দেয় যা C ও C++ প্রোগ্রামাররা মাথায় রেখে চলেন। শৃঙ্খলার উপর নির্ভর করার পরিবর্তে রাস্ট ক্লিনআপকে পূর্বানুমেয় করে তোলে।
যখন আপনি কপি করেন, আপনি দুইটি স্বাধীন কপি পান। যখন আপনি মুভ করেন, আপনি মূলটি হস্তান্তর করে দিচ্ছেন—মুভের পরে পুরনো ভেরিয়েবলটি সেটি ব্যবহার করতে পারে না।
রাস্ট অনেক হিপ-অলকেটেড মান (স্ট্রিং, বাফার, ভেক্টর ইত্যাদি)কে ডিফল্টভাবে মুভ হিসেবে আচরণ করে। কপির মাধ্যমে অমনভাবে অনির্বচনীয় কপি করা খরচসাপেক্ষ হতে পারে এবং বিভ্রান্তিকরও—যদি দুই ভেরিয়েবল একই বরাদ্দকে মালিক মনে করে তাহলে মেমরি বাগের সুযোগ তৈরি হয়।
নিচে একটি ক্ষুদ্র ছদ্ম-কোডে ধারণা:
buffer = make_buffer()
ownerA = buffer // ownerA owns it
ownerB = ownerA // move ownership to ownerB
use(ownerA) // not allowed: ownerA no longer owns anything
use(ownerB) // ok
// when ownerB ends, buffer is cleaned up automatically
একটি মানের সবসময় ঠিক একটি মালিক থাকার কারণে, রাস্ট জানে কখন একটি মান পরিষ্কার করতে হবে: যখন তার মালিক স্কোপ থেকে বের হয়। তার মানে স্বয়ংক্রিয় মেমরি ম্যানেজমেন্ট (আপনি প্রতিটি জায়গায় free() কল করবেন না) কিন্তু একটি গারবেজ কালেক্টরের প্রয়োজন ছাড়াই।
এই মালিকানা নিয়ম অনেক ক্লাসিক সমস্যা ব্লক করে:
রাস্টের মালিকানা মডেল কেবল সুরক্ষিত অভ্যাস উত্সাহ দেয় না—এটি অনেক ঝুঁকিপূর্ণ অবস্থাকে অনুপস্থিত করবে, যা বাকী রস্ট নিরাপত্তা বৈশিষ্ট্যের ভিত্তি।
মালিকানা ব্যাখ্যা করে কে মানের “মালিক”। বোরোইং ব্যাখ্যা করে প্রোগ্রামের অন্য অংশগুলো কীভাবে অস্থায়ীভাবে সেই মান ব্যবহার করতে পারে মালিকানা নেয়া ছাড়াই।
যখন আপনি রাস্টে কিছু বোরো করেন, আপনি সেটির একটি রেফারেন্স পান। আসল মালিক মেমরি ক্লিয়ানে দায়ী থাকে; বোরোয়ার কেবল একটি সময়ের জন্য ব্যবহার করার অনুমতি পায়।
রাস্টে দুটি ধরণের বোরো আছে:
&T): কেবল রিড-অনলি অ্যাক্সেস।&mut T): রিড-রাইট অ্যাক্সেস।রাস্টের কেন্দ্রীয় বোরো নিয়ম বলতে সহজ এবং ব্যবহারিকভাবে শক্তিশালী:
এই নিয়মটি এমন একটি সাধারণ বাগ প্রতিরোধ করে: প্রোগ্রামের এক অংশ ডেটা পড়ছে যখন অন্য অংশ তা পরিবর্তন করে নিচ্ছে।
একটি রেফারেন্স কেবল তখনই নিরাপদ যখন তা কখনও সেই ডেটার মৃত্যুর চেয়ে দীর্ঘজীবী না হয়—রাস্ট এটিকে লাইফটাইম বলে।
আপনাকে ফরমালিটি জানার প্রয়োজন নেই: একটি রেফারেন্স তার মালিকের মেয়াদ শেষ হওয়ার পরে টিকে থাকতে পারবে না।
রাস্ট এই নিয়মগুলোকে কম্পাইল টাইমে বোরো চেকার-এর মাধ্যমে জোরদার করে। একটি খারাপ রেফারেন্স বা ঝুঁকিপূর্ণ মিউটেশন ধরা না পাওয়ার আশায় না রেখে, রাস্ট এমন কোড কম্পাইল হতে দেবে না যা মেমরি ভুলভাবে ব্যবহার করতে পারে।
একটি শেয়ার্ড ডকুমেন্ট ভাবুন:
Concurrency হলো সেই জায়গা যেখানে “আমার মেশিনে এটা কাজ করে” বাগগুলো লুকাতে যায়। যখন দুইটি থ্রেড একই সময়ে চলে, সেগুলো আচরণে বিস্ময়কর ইন্টারঅ্যাকশন করতে পারে—বিশেষ করে যখন তারা ডেটা শেয়ার করে।
একটি ডাটা রেস ঘটে যখন:
ফলাফল শুধু “ভুল আউটপুট” নয়। ডাটা রেস রাষ্ট্রকে দূষিত করতে, প্রোগ্রাম ক্র্যাশ করাতে, বা সিকিউরিটি ঝুঁকি তৈরি করতে পারে। আরও খারাপ, এগুলো অনিয়মিত—লগ যোগ করলে বা ডিবাগ করলে বাগটি অদৃশ্য হয়ে যেতে পারে।
রাস্ট একটি অস্বাভাবিক অবস্থান নেয়: প্রতি প্রোগ্রামারকে সবসময় নিয়ম মনে রাখার উপর বিশ্বাস না করে, এটি বহু অনিরাপদ সমান্তরাল প্যাটার্নকে safe code-এ প্রকাশ করা অসম্ভব করার চেষ্টা করে।
উচ্চ স্তরে, রাস্টের মালিকানা-ও-বোরো নিয়ম এক থ্রেড কোডের বাইরে পৌঁছায়—এগুলো যা আপনি থ্রেডের মধ্যে শেয়ার করতে চান তা নিয়ন্ত্রণ করে। যদি কম্পাইলার প্রমাণ করতে না পারে যে শেয়ার করা অ্যাক্সেস সমন্বিত, তাহলে কোড কম্পাইল হবে না।
এটাকেই মানুষ রাস্তে “নিরাপদ সমান্তরালতা” বলে: আপনি এখনও সমান্তরাল প্রোগ্রাম লিখবেন, কিন্তু “ওহ-ওহ, দুই থ্রেড একই জিনিস লিখলো” ধরনের ভুলগুলোর একটি শ্রেণি প্রোগ্রামের চালানোর আগেই ধরা পড়ে।
ধরা যাক দুই থ্রেড কাউন্টার বাড়াচ্ছে:
রাস্টে আপনি কেবল নিরাপদ কোডে একই মানের পরিবর্তনশীল অ্যাক্সেস দুটো থ্রেডে দেয়া যাবে না। কম্পাইলার আপনার ইচ্ছাকে স্পষ্ট করতে বলবে—সাধারণত লকের পিছনে শেয়ার করা স্টেট রাখা বা মেসেজ পাসিং ব্যবহার করে—যাতে অ্যাক্সেস সমন্বয় করা হয়।
রাস্ট নিম্ন-স্তরের concurrency কৌশল নিষিদ্ধ করে না। এটি সেগুলোকে সংঘবদ্ধ করে। যদি আপনি সত্যিই এমন কিছু করতে চান যা কম্পাইলার সাধারণভাবে প্রমাণ করতে পারে না, আপনি unsafe ব্লক ব্যবহার করতে পারবেন, যা একটি সতর্কতা-লেবেলের মত কাজ করে: “এখানে মানুষের দায়িত্ব প্রয়োজন।” এই বিভাজন বেশিরভাগ কোডবেসকে নিরাপদ সাবসেটে রাখে, আবার যেখানে প্রয়োজন সেখানে সিস্টেম-স্তরের ক্ষমতাও দেয়।
রাস্টের সুরক্ষার খ্যাতি সম্পূর্ণরূপে অভেদ্য শোনালেও, সঠিকভাবে বলা উচিত—রাস্ট সেই সীমানা স্পষ্ট করে দেয় safe এবং unsafe প্রোগ্রামিংয়ের মধ্যে—এবং তা সহজে অডিটযোগ্য করে তোলে।
অধিকাংশ রাস্ট কোডই “safe Rust।” এখানে কম্পাইলার এমন নিয়ম জোরদার করে যা সাধারণ মেমরি বাগ প্রতিরোধ করে: use-after-free, double free, dangling pointers, এবং ডাটা রেস। আপনি এখনও লজিকগত ভুল করতে পারেন, কিন্তু সাধারণ ভাষা ফিচার দ্বারা সহজে মেমরি-নিরাপত্তা লঙ্ঘন করা যায় না।
একটি গুরুত্বপূর্ণ দিক: safe Rust মানে “ধীর গতি” নয়। অনেক উচ্চ-পারফরম্যান্স প্রোগ্রাম সম্পূর্ণভাবে safe Rust-এ লেখা—যেখানে কম্পাইলার সক্রিয়ভাবে অপ্টিমাইজ করে পারে কারণ এটি জানে নিয়মগুলো মানা হচ্ছে।
unsafe আছে কারণ সিস্টেম প্রোগ্রামিং কখনও কখনও এমন ক্ষমতা চায় যা কম্পাইলার সাধারণভাবে নিরাপদ বলে প্রমাণ করতে পারে না। সাধারণ কারণগুলো:
unsafe ব্যবহার করলেই সব চেক বন্ধ হয়ে যায় না। এটি কেবল কিছু অপারেশন (যেমন র-এ ডিরেফারেন্সিং) অনুমোদন করে যা অন্যথায় নিষিদ্ধ।
রাস্ট আপনাকে বাধ্য করে unsafe ব্লক ও ফাংশন চিহ্নিত করতে—এটি কোড রিভিউতে ঝুঁকি দৃশ্যমান করে। সাধারণ প্যাটার্ন হলো একটি ছোট “unsafe কোর” রাখা এবং সেটিকে সেফ API-তে ওয়াপ করে দেওয়া, ফলে প্রজেক্টের অধিকাংশ অংশ safe Rust-এ থাকে আর ছোট, ঠিকঠাক পরিচিত অংশ ইনভেরিয়েন্ট বজায় রাখে।
unsafe-কে একটি শক্তিশালী টুল ধরা উচিত:
ভালো করলে, unsafe Rust সিস্টেম প্রোগ্রামিংয়ের সেই অংশগুলোর নিয়ন্ত্রিত ইন্টারফেস হয়ে ওঠে—যেখানে ম্যানুয়াল নিখুঁততা দরকার, কিন্তু বাকি পুরো কোডবেস রাস্টের নিরাপত্তা সুবিধা পায়।
রাস্ট কাগজে কেবল চমৎকার ধারণা রাখে বলে “বাস্তব” হয়নি—এটি বাস্তব হয়ে উঠল কারণ Mozilla ঐ ধারণাগুলোকে চাপের নিচে টেস্ট করেছিল।
Mozilla Research এমন উপায় খুঁজছিল যাতে পারফরম্যান্স-ক্রিটিক্যাল ব্রাউজার কম্পোনেন্টগুলো কম সিকিউরিটি বাগ নিয়ে তৈরি করা যায়। ব্রাউজার ইঞ্জিনগুলো জটিল: তারা অন-ট্রাস্ট ইনপুট পার্স করে, প্রচুর মেমরি পরিচালনা করে, এবং অত্যন্ত সমান্তরাল কাজ করে। এই সম্মিলন মেমরি-সেফটি ত্রুটি ও রেস কন্ডিশনগুলো সাধারণভাবে মহাগুরুত্বপূর্ণ করে তোলে।
রাস্টকে সমর্থন করা ঐ লক্ষ্যটির সাথে খাপ খায়: সিস্টেম প্রোগ্রামিংয়ের গতি বজায় রেখে বড় বাগ শ্রেণী হ্রাস করা। Mozilla-র অংশগ্রহণ পাশাপাশিই বিশ্বের কাছে সংকেত পাঠিয়েছিল যে রাস্ট কেবল গ্রেডন হোয়ার-এর ব্যক্তিগত পরীক্ষা নয়—বরং একটি ভাষা যা পৃথিবীর কঠিনতম কোডবেসগুলোর একটির বিরুদ্ধে পরীক্ষা করা যেতে পারে।
Servo—পরীক্ষামূলক ব্রাউজার ইঞ্জিন প্রজেক্ট—হল রাস্টকে স্কেলে টেস্ট করার একটি উচ্চ-প্রোফাইল জায়গা। লক্ষ্য ছিল ব্রাউজার বাজার জেতা নয়। Servo ছিল একটি ল্যাব যেখানে ভাষা ফিচার, কম্পাইলার ডায়াগনস্টিক, এবং টুলিং বাস্তব পরিস্থিতির সাথে পরীক্ষা করা হয়েছিল: বিল্ড সময়, ক্রস-প্ল্যাটফর্ম সাপোর্ট, ডেভিএক্স, পারফরম্যান্স টিউনিং, এবং প্যারালালিজমে সঠিকতা।
আরও গুরুত্বপূর্ণভাবে, Servo ভাষার আশেপাশে ইকোসিস্টেম গঠন করতে সাহায্য করেছিল: লাইব্রেরি, বিল্ড টুলিং, কনভেনশন, এবং ডিবাগিং অনুশীলন—যা টয় প্রোগ্রামের বাইরে গেলে জরুরি।
বাস্তব প্রকল্পগুলো এমন ফিডব্যাক লুপ তৈরি করে যা ভাষা ডিজাইন যন্ত্রণা থেকে প্রতিলিপি করে না। যখন ইঞ্জিনিয়াররা বাধা পায়—অস্পষ্ট এরর মেসেজ, অনুপস্থিত লাইব্রেরি টুকরা, অস্বচ্ছ প্যাটার্ন—সেই ব্যথাদিকে দ্রুত দেখা যায়। সময়ের সাথে, ঐ ধারাবাহিক চাপ রাস্টকে promising ধারণা থেকে এমন কিছুতে পরিণত করেছে যা বড় পারফরম্যান্স-ক্রিটিক্যাল সফটওয়্যার টিমগুলো বিশ্বাস করতে শুরু করেছে।
এই ধাপের পরে রাস্টের বিস্তৃত বিবর্তন সম্পর্কে জানতে চাইলে দেখুন /blog/rust-memory-safety-without-gc।
রাস্ট একটি মাঝামাঝি জমিতে আছে: এটি C ও C++-এর প্রত্যাশিত পারফরম্যান্স ও নিয়ন্ত্রণ চায়, কিন্তু সেই ভাষাগুলো প্রায়শই লোকশৃঙ্খলা, টেস্টিং, ও ভাগ্যের উপর ছেড়ে দেয় এমন বড় একটি বাগ শ্রেণী মুছতে চায়।
C ও C++-এ ডেভেলপাররা সরাসরি মেমরি পরিচালনা করে—অলকেট, ফ্রি, এবং পয়েন্টারগুলোকে বৈধ রাখার নিশ্চয়তা দেয়। ঐ স্বাধীনতা শক্তিশালী, কিন্তু use-after-free, double-free, buffer overflow, এবং সূক্ষ্ম লাইফটাইম বাগ সৃষ্টি করা সহজ করে তোলে। কম্পাইলার সাধারণত আপনাকে বিশ্বাস করে।
রাস্ট সেই সম্পর্ক উল্টে দেয়। আপনি এখনও নিম্ন-স্তরের নিয়ন্ত্রণ পান (স্ট্যাক বনাম হিপ সিদ্ধান্ত, পূর্বানুমেয় লেআউট), কিন্তু কম্পাইলার মান সম্পর্কে নিয়ম জোরদার করে—কে একটি মানের মালিক এবং রেফারেন্স কতক্ষণ থাকতে পারে। “পয়েন্টার নিয়ম মানো” বলার বদলে রাস্ট বলে “কম্পাইলারকে নিরাপত্তার প্রমাণ দেখাও,” এবং safe Rust-এ এমন কোড কম্পাইল হবে না যা ঐ গ্যারান্টি ভাঙতে পারে।
গারবেজ-কালেক্টেড ভাষা (যেমন Java, Go, C#, বা অনেক স্ক্রিপ্টিং ভাষা) ম্যানুয়াল মেমরি পরিচালনার বদলে সুবিধা দেয়: অবজেক্টগুলো তাদের পৌঁছনীয়তা হারালে স্বয়ংক্রিয়ভাবে মুক্ত হয়ে যায়। এটি উৎপাদনশীলতায় বড় বাড়তি দেয়।
রাস্টের প্রতিশ্রুতি—“GC ছাড়া মেমরি নিরাপত্তা”—মানে আপনি রানটাইম GC-এর জন্য মূল্য পরেন না, যা অত্যন্ত ধাঁচা নিয়ন্ত্রণ দরকার হলে সহায়ক (লেটেন্সি, মেমরি ফিটিং, স্টার্টআপ টাইম, বা সীমিত পরিবেশে চালানোর ক্ষেত্রে)। ট্রেডঅফ হলো আপনি মালিকানা স্পষ্টভাবে মডেল করবেন এবং কম্পাইলারকে তা যাচাই করতে দেবেন।
রাস্ট প্রথমে কঠিন মনে হতে পারে কারণ এটি একটি নতুন মানসিক মডেল শেখায়: আপনি মালিকানা, বোরোইং, এবং লাইফটাইম চিন্তা করবেন, শুধু “একটি পয়েন্টার পাঠিয়ে দাও” নয়। প্রাথমিক ঘর্ষণ প্রায়শই শেয়ার করা রাজ্য বা জটিল অবজেক্ট গ্রাফ মডেলিং-এ দেখা যায়।
রাস্ট সাধারণত সেই দলগুলোর জন্য দারুণ—যারা নিরাপত্তা-সংবেদনশীল এবং পারফরম্যান্স-ক্রিটিক্যাল সফটওয়্যার তৈরি করে—ব্রাউজার, নেটওয়ার্কিং, ক্রিপ্টোগ্রাফি, এমবেডেড, এমন ব্যাকেন্ড সার্ভিস যেখানে নির্ধারিত কর্মক্ষমতা জরুরি। যদি আপনার দল দ্রুত পুনরাবৃত্তি করতে চায় এবং নিম্ন-স্তরের নিয়ন্ত্রণ কম প্রয়োজনীয়, তাহলে GC-ভিত্তিক ভাষা এখনও ভাল পছন্দ হতে পারে।
রাস্ট সব জায়গায় প্রতিস্থাপন নয়; এটি একটি শক্তিশালী অপশন যখন আপনি C/C++-স্তরের পারফরম্যান্স চান এবং সেই সঙ্গে এমন নিরাপত্তা গ্যারান্টি চান যা ভরসা করা যায়।
রাস্ট “আরও সুন্দর C++” হয়ে নজর কেড়েনি। এটি কথোপকথন পরিবর্তন করেছিল কারণ এটি জোর দিয়েছে যে নিম্ন-স্তরের কোড একসঙ্গে দ্রুত, মেমরি-নিরাপদ, এবং খরচ সম্পর্কে স্পষ্ট হতে পারে।
রাস্ট আসার আগে দলগুলো প্রায়ই মেমরি বাগকে পারফরম্যান্সের বিনিময় হিসেবে ধরে নিত, তারপর টেস্টিং, কোড রিভিউ, এবং ঘটনার পরে ফিক্স-এ ভর করে ঝুঁকি ম্যানেজ করত। রাস্ট একটি ভিন্ন বাজি রেখেছিল: ভাষায় সাধারণ নিয়মগুলো (কে ডেটা owns করে, কে এটিকে বদলায়, কখন এটি বৈধ থাকবে) encode করে দাও যাতে কোডের বড় শ্রেণী কম্পাইল টাইমেই প্রত্যাখ্যাত হয়।
এই পরিবর্তন গুরুত্বপূর্ণ ছিল কারণ এটি ডেভেলপারদেরকে “পারফেক্ট হতে বলছে” না—এটি বলছে স্পষ্ট হও, তারপর কম্পাইলার সেই স্পষ্টতাকে প্রয়োগ করবে।
রাস্টের প্রভাব বিভিন্ন সিগন্যালে দেখা যায়: পারফরম্যান্স-সেনসিটিভ সফটওয়্যার সরবরাহকারী কোম্পানিগুলোর আগ্রহ বাড়া, বিশ্ববিদ্যালয় কোর্সে উপস্থিতি বেড়েছে, এবং টুলিং যা “রিসার্চ প্রজেক্ট” থেকে “ডেইলি ড্রাইভার” অনুভব করায়—প্যাকেজ ম্যানেজমেন্ট, ফরম্যাটিং, লিন্টিং, এবং ডকুমেন্টেশন ওয়ার্কফ্লো আউট-অফ-দ্য-বক্স কাজ করে।
এর মানে রাস্ত সবসময় সেরা বিকল্প নয়—কিন্তু এটি নিরাপত্তা-ডিফল্ট ধারণাটিকে আর একটি বিলাসিতা না রেখে বাস্তবসম্মত করে তুলেছে।
রাস্ট প্রায়শই বিবেচিত হয়:
“নতুন মানদণ্ড” মানে সব সিস্টেম রাইডেক করে রিস্টে লেখা হবে না। এর মানে হলো মানটি উঠে গেছে: দলগুলো এখন আরোই প্রশ্ন করে, কেন মেমরি-অসেফ ডিফল্ট গ্রহণ করা হবে যখন করা যায় না? রাস্ট গ্রহণ না করলেও, তার মডেল ইকোসিস্টেমকে নিরাপদ API, স্পষ্ট ইনভেরিয়েন্ট, এবং সঠিকতা টুলিংকে মূল্য দিতে প্রভাবিত করেছে।
আরও ইঞ্জিনিয়ারিং ব্যাকস্টোরিযের জন্য /blog ব্রাউজ করুন।
রাস্টের উদ্ভব কাহিনির একটি সহজ থ্রুপথ আছে: এক ব্যক্তির সাইড-প্রজেক্ট (গ্রেডন হোয়ার-এর নতুন ভাষা পরীক্ষা) একটি জটিল সিস্টেম প্রোগ্রামিং সমস্যার সাথে মুখোমুখি হয়, এবং সমাধানটি কঠোরও কিন্তু ব্যবহারিক—এমন কিছু যা বাস্তবে প্রয়োগযোগ্য।
রাস্ট একটি অনেকেই ধরে নেওয়া ট্রেডঅফকে পুনরায় ফ্রেম করে:
প্রায়োগিক পরিবর্তন শুধু “রাস্ট নিরাপদ” বলা নয়। এটি যে নিরাপত্তা ভাষার একটি ডিফল্ট বৈশিষ্ট্য হতে পারে, কোড রিভিউ ও টেস্টিং দ্বারা আমৃত্যু প্রয়োজনীয় অনুশীলন নয়—এটাই মূল ব্যাপার।
আপনি যদি কৌতূহলী হন, পুরো রিফ্যাক্টরের প্রয়োজন নেই—রাস্ট কীভাবে লাগে তা জানার জন্য ছোটভাবে শুরু করুন।
শুরু করুন ছোট:
উপায়: একটি “পাতলা স্লাইস” লক্ষ্য নিন—যেমন “একটা ফাইল পড়ো, ট্রান্সফর্ম করো, আউটপুট লিখো”—এবং পরিষ্কার কোড লেখায় ফোকাস করুন, জটিলতার উপর নয়।
প্রজেক্টের ভিতরে একটি রাস্ট কম্পোনেন্ট প্রোটোটাইপ করলে, আশেপাশের পিসগুলো দ্রুত রাখা (অ্যাডমিন UI, ড্যাশবোর্ড, কন্ট্রোল প্লেন, সহজ API) সাহায্য করবে, এবং আপনি রাস্ট সার্ভিসের সঙ্গে পরিষ্কার বাউন্ডারির মাধ্যমে ইন্টিগ্রেট করতে পারবেন। প্ল্যাটফর্মগুলো যেমন Koder.ai সেই ধরনের “গ্লু” ডেভেলপমেন্ট ত্বরান্বিত করতে পারে—চ্যাট-চালিত ওয়ার্কফ্লো দিয়ে React ফ্রন্টএন্ড, Go ব্যাকএন্ড, এবং PostgreSQL স্কিমা দ্রুত জেনারেট করে, তারপর সোর্স এক্সপোর্ট করে রাস্ট সার্ভিসের সাথে একীভূত করা যায়।
আপনি যদি একটি দ্বিতীয় পোস্ট চান, কোনটা সবচেয়ে উপকারী হবে?
unsafe কিভাবে দায়িত্বশীলভাবে ব্যবহার করা হয়আপনার প্রসঙ্গ (আপনি কী তৈরি করেন, এখন কোন ভাষা ব্যবহার করেন, এবং কী নিয়ে আপনি অপ্টিমাইজ করছেন) দিয়ে উত্তর দিন—আমি পরের বিভাগটি আপনার প্রয়োজন অনুযায়ী কাস্টমাইজ করব।
সিস্টেম প্রোগ্রামিং হলো এমন কাজ যা হার্ডওয়্যারের কাছাকাছি এবং প্রডাক্টের ঝুঁকিপূর্ণ অংশে বসে—যেমন ব্রাউজার ইঞ্জিন, ডেটাবেস, অপারেটিং সিস্টেম কম্পোনেন্ট, নেটওয়ার্কিং, এবং এমবেডেড সফটওয়্যার।
এতে সাধারণত দরকার পড়ে ভরত্যোগযোগ্য কর্মক্ষমতা, নিম্ন-স্তরের মেমরি/কন্ট্রোল, এবং উচ্চ নির্ভরযোগ্যতা, যেখানে ক্র্যাশ এবং সিকিউরিটি বাগগুলোর দাম খুব বেশি।
এর মানে হলো রাস্ট এমনভাবে লক্ষ্য রাখে যে সাধারণ মেমরি বাগ (যেমন use-after-free এবং double-free) থেকে রক্ষা করবে কোনো রানটাইম গারবেজ কালেক্টরের উপর নির্ভর না করে।
রানটাইমে মেমরি স্ক্যান করার পরিবর্তে, রাস্ট অনেক নিরাপত্তা চেককে কাম্পাইল টাইমে ঠেলে দেয়—মালিকানা (ownership) এবং ধার (borrowing) নিয়মের মাধ্যমে।
স্যনিটাইজার বা স্ট্যাটিক অ্যানালাইসিসের মতো টুলগুলো অনেক ইস্যু ধরতে পারে, কিন্তু যখন ভাষা নিজেই অনির্দিষ্ট পয়েন্টার এবং লাইফটাইম প্যাটার্নকে মুক্তভাবে অনুমতি দেয়, তখন সেগুলো সাধারণত পুরোপুরি গ্যারান্টি দিতে পারে না।
রাস্ট ভাষা এবং টাইপ সিস্টেমে মূল নিয়মগুলো বেস করে দেয়, যাতে কম্পাইলার ডিফল্টভাবে পুরো শ্রেণীর বাগ প্রত্যাখ্যান করতে পারে, আবার প্রয়োজন হলে স্পষ্টভাবে চিহ্নিত ‘এস্কেপ হ্যাচ’ রেখে দেয়।
গারবেজ কালেক্টর(runtime GC) রানটাইম ওভারহেড এবং সবচেয়ে গুরুত্বপূর্ণভাবে কম পূর্বানুমেয় লেটেন্সি (যেমন পজ বা সংগ্রহ কাজ যখন রানটাইম সিদ্ধান্ত নেয় তখন ঘটে) যোগ করতে পারে।
ব্রাউজার, রিয়েল-টাইম কন্ট্রোলার, বা কম-লেটেন্সি সার্ভিসের মতো ডোমেইনে worst-case আচরণই গুরুত্বপূর্ণ—তাই রাস্ট নিরাপত্তা দেয়ার সময়ও অধিক পূর্বানুমেয় কর্মক্ষমতা রাখতে চায়।
মালিকানা (ownership) অর্থ হলো প্রতিটি মানের একটি একক “দায়িত্বশীল” অংশীদার থাকে, যিনি মানটির ব্যবহারের শেষ হলে সেটি পরিষ্কার করার জন্য দায়ী। যখন সেই মালিকের স্কোপ শেষ হয়, মানটি নিজে থেকেই ক্লিন আপ হয়ে যায়।
এতে cleanup পূর্বানুমেয় হয় এবং একই বরাদ্দ নিয়ে দুই জায়গা যখন একসাথে মালিকানা দাবি করে—এমন পরিস্থিতি রোধ হয়।
একটি move মানে একটি ভেরিয়েবল থেকে অন্য ভেরিয়েবলে মালিকানা হস্তান্তর; move-র পরে পুরনো ভেরিয়েবলটি আর মানটি ব্যবহার করতে পারে না।
এটি এই ধরনের দুর্ঘটনা থেকে রক্ষা করে—এক allocation-র দুই মালিক থাকার ভুল, যা double-free বা use-after-free-এর মূল কারণ হতে পারে।
বোরো করা (borrowing) মানে কোনো কোড অংশ সাময়িকভাবে একটি মান ব্যবহার করতে পারে রেফারেন্সের মাধ্যমে, কিন্তু মালিকানা নেয় না।
মূল নিয়ম: অনেক রিডার বা একটাই রাইটার — একই সময়ে একাধিক shared reference (&T) থাকতে পারে, অথবা একটিমাত্র mutable reference (&mut T) থাকতে পারে, কিন্তু উভয় একসাথে থাকতে পারবে না।
এটি বড় একটি বাগ শ্রেণী—পড়ার সময় অন্য কোথাও থেকে ডেটা পরিবর্তন হওয়া—রোধ করে।
লাইফটাইম হলো “কতক্ষণ একটি রেফারেন্স বৈধ থাকবে।” রেফারেন্স কখনই তার পয়েন্ট করা ডেটার চেয়ে দীর্ঘজীবী হতে পারে না।
বোরো চেকার (borrow checker) এই নিয়মগুলো কম্পাইল টাইমে-Enforce করে, ফলে যে কোডগুলো dangling reference তৈরি করতে পারে সেগুলো রান করা থেকেই অস্বীকার হয়ে যায়।
ডাটা রেস ঘটে যখন:
রাষ্টের মালিকানা/বোরো নিয়মগুলো concurrency-র ক্ষেত্রেও প্রভাব ফেলে, যাতে নিরাপদ (safe) কোডে এমন ঝুঁকিপূর্ণ শেয়ারিং প্যাটার্ন প্রকাশ করা কঠিন বা অসম্ভব হয়। এর ফলে বহু ধরণের ডাটা রেস কম্পাইল টাইমেই আটকায়।
বেশিরভাগ কোডই safe Rust-এ লেখা হয়, যেখানে কম্পাইলার মেমরি-নিরাপত্তার নিয়মগুলো জোরদার করে।
unsafe হলো স্পষ্টভাবে চিহ্নিত একটি এস্কেপ হ্যাচ—এগুলোর দরকার পড়ে যখন কম্পাইলার সাধারণভাবে নিরাপদ বলে প্রমাণ করতে পারে না (যেমন FFI, হার্ডওয়্যার বা পারফরম্যান্স-ক্রিটিক্যাল কেস)।
শ্রেষ্ঠ অনুশীলন হলো unsafe ব্লকগুলো ছোট রাখা, স্পষ্ট মন্তব্য দেওয়া, অতিরিক্ত রিভিউ করা এবং টেস্টিং যোগ করা—তাহলে unsafe-কে একটি নিয়ন্ত্রিত আন্তঃফেস হিসেবে ব্যবহার করা যায়।