بسیاری از زبانهای مدرن دارای زبالهگیر هستند تا حافظه شما را تمیز نگه دارد. اما چگونه کار می کند و آیا واقعاً می تواند مشکلات حافظه را برای شما برطرف کند؟
زباله جمع کن (GC) یک مدیر حافظه است. بسیاری از زبان های برنامه نویسی دارای GC داخلی هستند. این ویژگی به طور خودکار حافظه را در یک برنامه تخصیص داده و از آن جدا می کند. این حافظه بسته و استفاده نشده را آزاد می کند که سرعت برنامه شما را کند می کند.
زیبایی GC در این است که بدون نیاز به انجام کاری، حافظه را از طرف شما آزاد می کند. بنابراین، ممکن است آن را چنان ویژگی ضروری در نظر بگیرید که انتظار داشته باشید هر زبان برنامه نویسی آن را داشته باشد. بدبختانه، این آن مورد نیست؛ حتی زبان محبوبی مانند C می تواند فاقد GC باشد.
تخصیص حافظه چگونه کار می کند؟
وقتی برنامه ای را به هر زبان برنامه نویسی اجرا می کنید، سیستم عامل شما یک پشته داده در حافظه آن برنامه ذخیره می کند. این برنامه مالک و اشغال این پشته داده تا زمانی که اجرا کامل شود. اگر برنامه شما به حافظه بیشتری نسبت به آنچه در دسترس است نیاز دارد، می تواند به صورت پویا حافظه بیشتری را از پشته حافظه سیستم عامل اختصاص دهد.
در برنامه نویسی، متغیر یک مکان حافظه را نشان می دهد. بنابراین، هنگامی که یک متغیر جدید را اعلام می کنید، زبان برنامه نویسی فضایی را در حافظه برای این متغیر اختصاص می دهد. متغیر اکنون یک آدرس حافظه خواهد داشت. تا زمانی که مقداری را به این متغیر اختصاص ندهید، بدون مقدار اولیه باقی می ماند و ممکن است حاوی مقداری زباله باشد.
اگر یک زبان برنامه نویسی به شما اجازه می دهد که یک متغیر را بدون مقداردهی اولیه آن اعلام کنید، آنگاه یک متغیر پویا است. این بدان معنی است که مقداری که به متغیر اختصاص می دهید ممکن است در طول زمان تغییر کند. با این حال، مکان حافظه متغیر تا زمانی که آن را توزیع نکنید، ثابت می ماند.
تخصیص حافظه چگونه کار می کند؟
تخصیص حافظه فرآیندی مشابه برای همه زبان های برنامه نویسی است. اما روش مربوط به تخصیص حافظه متفاوت است. دو نوع روش تخصیص حافظه وجود دارد. دستی و اتوماتیک GC انتقال خودکار را انجام می دهد.
تخصیص حافظه بدون زباله گرد
زبان برنامه نویسی C از GC برای تخصیص حافظه استفاده نمی کند. بنابراین، برنامه نویسان C باید حافظه را به صورت دستی تخصیص و توزیع کنند. C امکان تخصیص حافظه پویا را برای مواقعی که نمی دانید در زمان کامپایل چقدر حافظه در زمان اجرا استفاده خواهید کرد را می دهد.
کتابخانه استاندارد (stdlib.h) شامل توابعی است که C برای مدیریت تخصیص حافظه پویا استفاده می کند. این توابع عبارتند از:
- malloc(): اندازه خاصی از حافظه را اختصاص می دهد و یک اشاره گر به آن حافظه برمی گرداند. اگر حافظه کافی در مخزن حافظه سیستم عامل موجود نباشد، آن را null برمی گرداند.
- free(): یک بلوک خاص از حافظه را اختصاص می دهد و آن را به استخر حافظه سیستم عامل باز می گرداند.
نمونه برنامه C
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *ptr; // declare pointer
int j; // declare counter
// allocate space for 200 integers
ptr = (int *) malloc(200 * sizeof(int));
// insert integer values into the memory allocated
// and print each value to the console
for (j = 0; j < 200; j++)
{
ptr[j] = j;
printf("%d\t",ptr[j]);
}
// deallocate the previously allocated memory
free(ptr);
return 0;
}
کد بالا با استفاده از تابع malloc() حافظه را به ذخیره 200 مقدار صحیح اختصاص می دهد. از یک اشاره گر برای دسترسی به این مکان حافظه استفاده می کند و 200 مقدار صحیح را در آن ذخیره می کند. اشاره گر همچنین داده های ذخیره شده در محل حافظه را روی کنسول چاپ می کند. در نهایت، برنامه حافظه تخصیص داده شده قبلی را با استفاده از تابع ()free اختصاص می دهد.
تخصیص حافظه با زباله جمع کن
چندین زبان برنامه نویسی محبوب از GC برای مدیریت حافظه استفاده می کنند. این امر زندگی برنامه نویسانی را که از این زبان ها استفاده می کنند بسیار آسان می کند. C# و Java دو زبان برنامه نویسی هستند که از GC استفاده می کنند.
سی شارپ GC
در زبان برنامه نویسی C#، یک GC تخصیص و تخصیص آدرس های حافظه را مدیریت می کند. بنابراین، یک برنامه نویس سی شارپ نیازی به نگرانی در مورد عدم تخصیص یک شی پس از تکمیل هدف خود ندارد.
C# GC یک مخزن حافظه به نام هیپ مدیریت شده را برای هر فرآیند (یا برنامه) جدید راه اندازی می کند. تابع VirtualAlloc() را برای تخصیص حافظه و تابع VirtualFree() را برای انتقال آن فراخوانی می کند. بهترین بخش این است که همه اینها در پس زمینه بدون هیچ تلاشی از شما، برنامه نویس، اتفاق می افتد.
C# GC دارای یک موتور بهینه سازی است که از آن برای تصمیم گیری در مورد زمان اختصاص حافظه استفاده می کند. موتور بهینهسازی ریشه برنامه را بررسی میکند تا مشخص کند کدام اشیا دیگر مورد استفاده قرار نمیگیرند. این کار را با ایجاد یک نمودار انجام می دهد که از ریشه برنامه به اشیاء متصل گسترش می یابد. این ریشه شامل فیلدهای استاتیک، متغیرهای محلی و غیره است. هر شیئی که به ریشه برنامه متصل نباشد زباله است.
موتور بهینه سازی GC به تنهایی حافظه را جمع آوری نمی کند. ابتدا باید یک درخواست تخصیص حافظه جدید وجود داشته باشد. اگر سیستم مقدار کمی حافظه در دسترس داشته باشد، موتور بهینهسازی GC وارد عمل میشود.
جاوا GC
در جاوا، یک GC همچنین تخصیص و توزیع آدرس های حافظه را مدیریت می کند. با این حال، جاوا در حال حاضر دارای چهار نوع مختلف جمعآوری زباله است:
- Garbage-First (G1)
- سریال
- موازی
- Z Garbage Collector (ZGC)
جمعآوری زباله G1، GC پیشفرض جاوا از زمان انتشار کیت توسعه جاوا (JDK) 9 است. جاوا دادهها را در اشیا سازماندهی میکند و این اشیاء را در یک پشته با اندازه ثابت ذخیره میکند. زباله جمع کن G1 پشته را به نواحی با اندازه مساوی تقسیم می کند. سپس این مناطق پشته را به دو بخش تقسیم کرد. نسل جوان و پیر
هر بار که یک شی جدید ایجاد می کنید، تخصیص فضا برای این شی در نسل جوان اتفاق می افتد. جمعآوری زباله G1 با استفاده از فرآیند پیری، اشیاء موجود در مناطق جوان را در مناطق قدیمی کپی میکند. همچنین اشیایی را که از قبل در منطقه قدیمی هستند در یک منطقه قدیمی کپی می کند.
جمعآوری زباله G1 بیشتر حافظه خود را در نسل جوان انجام میدهد و گهگاه به بخش نسل قدیم سر میزند.
مزایای داشتن یک زباله جمع کن چیست؟
مزیت داشتن زباله جمع کن این است که از فکر کردن به مدیریت حافظه در هنگام نوشتن کد جلوگیری می کند. این به شما زمان می دهد تا روی سایر جنبه های مهم برنامه خود تمرکز کنید. با این حال، چندین مزیت دیگر ارزش برجسته کردن دارد.
بازیابی اشیاء استفاده نشده و آزاد کردن حافظه، اجرای برنامههای پاکتر را فراهم میکند. اگر برنامه شما در اسرع وقت حافظه را آزاد کند، ردپای حافظه کمتری خواهد داشت و می تواند کارآمدتر اجرا شود.
جمع آوری زباله خطاهای مربوط به مدیریت حافظه مانند نشت و خطاهای اشاره گر را کاهش می دهد. این به این دلیل است که فرآیند دیگر به برنامه نویس و توانایی آنها برای نوشتن کد دقیق وابسته نیست.