Dynamic Memory Allocation
আমরা একটা প্রোগ্রামে যেসব ভ্যারিয়েবল, Array ইত্যাদি ইউজ করি এগুলাতো মেমোরিতে একটা জায়গা দখল করে তাই
না? এটা নিয়ে কি কোনো সন্দেহ আছে?
তো এই জায়গা দখল করার প্রক্রিয়াটা দুইভাবে সম্ভব। ১.
static ২. Dynamic
Static –স্থির
Dynamic – গতিশীল
“মেমোরি দখল করে” এটার ইংরেজী Memory Allocation. দখলটা দুইভাবে
করতে পারে, , , । যদি static ভাবে করে তাহলে static memory
allocation , যদি dynamically করে তাহলে dynamic memory allocation বলে।
Dynamic Memory Allocation বলতে কি বুঝাচ্ছে?
আমরা প্রোগ্রাম লিখে রান করি না? রান হচ্ছে (running) এই
অবস্থায় যদি মেমোরিতে নতুন ভাবে জায়গা নেই তখন সে গতিশীল অবস্থায় জায়গা দখল করছে দেইখা
ঐটা রে dynamic বা গতিশীল মেমোরি দখল বলে। মানে এইক্ষেত্রে আমরা আগে থেকে জানবো না কতটূকু
জায়গা দখল করবে, রান হয়ে যাবে then ওর যত ইচ্ছা জায়গা নিবে কিন্তু এটা প্রোগ্রাম রান
হউয়ার পরে রানিং অবস্থায় হচ্ছে এইজন্য এটাকে
dynamic memory allocation বলে।
এই যে রানিং হউয়ার পরে ইচ্ছামত জায়গা নিতে পারছে এই বৈশিষ্ট্য
কাজে লাগিয়ে আমরা আমাদের একটা সমস্যা দূর করতে পারি ।
কি সমস্যা?
:- Array নিয়ে কাজ করার সময় আগে থেকেই সাইজ বা দখল করার জায়গার
পরিমাপ বলে দেয়া লাগত, পরে আর কম বেশী করতে পারতাম না।
int ar[100]; ১০০ সাইজ ডিক্লেয়ার করেছি এখন যদি আমার ২টা
লাগে তাহলে বাকি ৯৮টা (৯৮*৪ byte) লস ।
এইখানে Dynamic Memory Allocation এর ব্যাপারটা কাজে লাগিয়ে
আমরা আগে থেকে কিছু বলে দিব না, রান করার পরে আমাদের যেটুক লাগবে সেটুক দখল করে নিব,
তাহলে জায়গা short পড়বে না আবার বেশী দখলও করব না, যেটুক লাগবে সেটুক নিব ।
Static memory allocation এর ব্যাপারটা কি ছিল?
:- int a;
int
ar[10]; //সাইজ ১০ // int টাইপ = 4 বাইট
Array = 10 * 4 = 40 byte
Variable ‘a’ = 4 byte
Total
= 44 byte
এভাবে আমরা আগে থেকেই বলতে পারতাম আমাদের প্রোগ্রামে কত মেমোরি
নিবে, অথবা compile টাইমে কম্পাইলার জানতো যে এতটুক মেমোরি নিয়ে তাকে কাজ করতে হবে
যে মেমোরি রানটাইমে বাড়ানো বা কমানো সম্ভব না অথবা আমরা এতদিন যতসব প্রোগ্রাম লিখেছি সব
static memory allocation ছিল ।
static memory এর ব্যাপারটা আমাদের নতুনভাবে শেখার কিছু নাই ,এখন আমরা Dynamically কিভাবে মেমোরি
দখল (allocate) করতে হয় সেটা শিখব, ।
সি প্রোগ্রামে Dynamically Memory দখলের জন্য কিছু মেথড বা
ফাংশন পাওয়া যায়
1. malloc()
2. calloc()
3. realloc()
4. free()
উপরের ৪টা জিনিস আপনাকে মেমোরি দখল করতে সাহায্য করবে, তাদের
কাজের ধরণ জানব যে কে কিভাবে কাজ করে, তারপর আপনি decision নিবেন যে কাকে কখন ব্যবহার
করবেন।
মানে ধরেন আপনি অন্যের মাটি দখল করবেন তো যার মাটি দখল করবেন
দেখা গেল সে গ্যাঞ্জাম ছাড়াই মাটি দিয়ে দিতে রাজি, তাহলে তো আর আপনার মারামারি করার
দরকার নাই, তখন দেখবেন আপনার ঐ ৪ টা লোকের
(malloc(), calloc(), realloc(), free() ) মধ্যে কে মারামারি ছাড়া দখল করে তখন তাকে ব্যবহার
করবেন । মানে অবস্থা বুঝে ব্যবস্থা নিবেন ।
৪ জন লোকেরতো দায় পড়েনি আপনাকে সাহায্য করার তাই না? , তাই
আপনার দরকার হলে আপনাকে ওদের নিয়ে আসতে হবে, আপনার প্রোগ্রামের মধ্যে ওরা যেই হেডার ফাইলে থাকে ঐটাকে include করতে হবে। ওরা
standard library header file এর মধ্যে থাকে ।
#include<stdlib.h> //stdlib stands
for standard library
মানে standard library ডট h কে include করে নিতে হবে এগুলা ব্যবহারের আগে ।
এখন আমরা ঐ ৪ জন লোকের পরিচয় বা কাজের ধরণ জানতে হবে।
malloc():
(এগুলা বলতে হয় না, কিন্তু না বললেও নয় , শুনবেন?
malloc() শিখলেই হবে, বাকি গুলা সেরকম ব্যবহার হবেই না J কাউকে বইলেন না )
malloc(memory_size);
malloc প্যারামিটার হিসেবে সাইজ নেয়, মানে আপনি কত সাইজের
মেমোরি allocate করতে চান এই সাইজটা আপনাকে পাস করে দিতে হবে তাহলেই কাজ শেষ , এই সাইজটা কিন্তু byte
হিসেবে নেয় ,
মানে int ar[10]; দশ সাইজের array declare করতে চান, তাহলে
সাইজ কতো হবে / লাগবে ? int টাইপের জন্যে প্রত্যেকের সাইজ 4 করে ১০টা
মোট সাইজ = ১০ *
৪ = ৪০ byte
তাহলে আপনি দিবেন malloc(40);
কিন্তু এভাবে সবসময় ক্যাল্কুলেশন করে সাইজ দেয়াটা বড্ড ঝামেলার
, আবার কোন data type এর সাইজ কত এটা যদি আপনি না জানেন ?
তাই আরেকটা method/function ব্যবহার করা হয়
sizeof();
sizeof( এর ভিতরে যা দিবেন তার ওজন/সাইজ বলে দিবে) , যেমনঃ
sizeof(int)
gives 4
sizeof(float)
gives 4
sizeof(double)
gives 8
sizeof(আপনি)
gives কত? আপনার ওজন :p
এটা মূলত ব্যবহারের কারন আমরা যখন structure নিয়ে কাজ করব
তখন structure এর সাইজ আলাদাভাবে বের করা বহুত ঝামেলা, কিন্তু এইখানে শুধু নাম দিয়ে
দিলেই সাইজটা পেয়ে যাবেন, আবার সব সিস্টেমে int এর সাইজ ৪(চার) বাইট হয়না কোনো কোনো
কম্পিউটারে ২ বাইট ও হয় , কিন্তু এটা আপনি কিভাবে জানবেন, ঐজন্যে sizeof() ইউজ করাই
better ।
struct structure_Name{
int a;
double d;
int
arr[5];
};
structure ও একটা ডেটা টাইপ, ইউজার ডিফাইন/ combine ডেটা
টাইপ আর কি, তো এই structure এর সাইজ কতো?
sizeof(structure_Name); gives you 32bytes
32 byte হয় এটা আপনাকে calculation করতে হবে না, শুধু নামটা দিয়ে দিবেন sizeof() এর মধ্যে আর সাইজ পেয়ে যাবেন , এইজন্যে আমরা malloc() এর ভিতরে
sizeof() ইউজ করব।
#include<'stdio.h>
#include<'stdlib.h>
int main()
{
int n;
int *ptr;
printf("কয়জনের জায়গা নিবি? ");
scanf("%d",&n); //if n=5
ptr=malloc(n * sizeof(int)); //sizeof(int)= 4
//malloc(5 * 4) //malloc(20)
}
malloc stands for memory allocation
এইখানে আমরা ইউজারকে জিজ্ঞেস করছি কয়টা ইন্টিজারের জন্য
memory allocate করতে চাই ? যেটা ইনপুট দিবে ঐটাকে ৪(চার) দিয়ে গুণ বা
sizeof(int) এর সাথে গুন দিয়ে পাস করে দিচ্ছি
।
এখন malloc(20) দিলাম এইটা আসলে কি কাজ করছে?
Memory তে যেয়ে ২০ সাইজের একটা বক্স তৈরী করছে, তারপর ঐ বক্সের
একদম শুরুর address টা আপনাকে দিয়ে দিচ্ছে, মানে এটা রিটার্ন করবে শুধু ১০০০। আমরা শুরুর address টা জানলেই ptr++ করে করে পরের address গুলাও বের করতে পারব।
|
|
1000 1004 .. . . . . . . . . . .. . . . . . .. .. . ..1016
আপনাকে কি দিচ্ছে? First point এর address (1000) দিচ্ছে, এখন এই
address কি আপনি পকেটে ভরে রাখবেন ? address store করে রাখতে হবে, কেন? যাতে পরে ঐ
address ইউজ করে মেমোরির ঐ জায়গা ইউজ করতে পারেন, তো address store করে রাখতে পারে
বা কে বা কারা?
উত্তরঃ পয়েন্টার
*পয়েন্টার যেই টাইপের হবে সেই সেম টাইপের address রাখতে পারবে
তাই উপরের কোডে int *ptr; //pointer declare করেছি
ptr = malloc(n * sizeof(int) ) ; // malloc জায়গা দখল করে আপনাকে দখল করা জায়গার
address দিচ্ছে, যেটা ptr এর মধ্যে রাখছেন আপনি,
আপনার যখন যেই ডেটা টাইপের মেমোরি দরকার সেই টাইপের পয়েন্টারের মধ্যে তার address রেখে দিচ্ছেন, কিন্তু malloc() আসলে কেমন address রিটার্ন করছে যাতে আপনি int type pointer এর মধ্যেও address টা store করে রাখতে পারছেন,আবার double type এর পয়েন্টারেও রাখতে পারছেন। কারণটা হলো malloc() void type address return করে , মানে সবাই নিতে পারে এইরকম একটা টাইপ , কিন্তা এটার টাইপ স্পেসিফিক করার জন্য এটাকে type casting করে নিতে হয়, না করলেও কাজ করবে but এটা করাকে good practice বলে।
malloc() void টাইপ রিটার্ন করে, আমাদের টাইপ কাস্টিং করে
নিতে হয়। যেমনঃ
int *ptr; double *pt; structure name *s1;
ptr= (int*)
malloc(sizeof(int));
pt= (double*) malloc(sizeof(double));
s1= (structure name*) malloc(sizeof(structure
name));
structure নিয়ে পরের পোস্টে পড়ব in sha Allah .
malloc শুধু জায়গা দখল করে দেয়, জায়গায় কোনো ভ্যালু রাখে
না,
এটা বলার কারণ calloc() জায়গা দখল করে সবগুলা 0 দিয়ে initialize করে দেয়।
যদি জায়গা ফাকা না থাকে তাহলে malloc() returns NULL
calloc():
malloc() আর calloc() এর কাজ একই,
শুধু calloc() ২টা প্যারামিটার নেয়
calloc(কয়টা variable, প্রত্যেকের সাইজ);
calloc(5, 4); আবার এটা ব্লক ব্লক ভাবে মেমোরি দখল করে
|
0 |
0 |
0 |
0 |
0 |
১০০০
১০০৪ ১০০৮ ১০১২ ১০১৬
malloc(), calloc() একই পার্থক্য শুধু এইটুকুই, এইখানে যেহেতু
সবগুলা 0 দিয়ে initialize করছে তাই কমপ্লেক্সিটি একটু , একদম একটু বেশি হতে পারে ।
#include <'stdio.h>
#include <'stdlib.h>
int main () {
int n;
int *ptr;
printf("How many variables u want to allocate?\n");
scanf("%d",&n);
ptr= (int*)calloc(n, sizeof(int));
//same code malloc diye korte chaile evabe
// ptr =(int*) malloc(n * sizeof(int));
printf("Enter %d numbers:\n",n);
int i;
for( i=0 ; i < n ; i++ ) {
scanf("%d",ptr+i); //scanf e '&' dite hoy, bt dilam na ken?
//answer akdom last e
//scanf er line ta evabeo hoy
//scanf("%d",&ptr[i]);
}
printf("The numbers entered are: ");
for( i=0 ; i < n ; i++ ) {
printf("%d ",ptr[i]);
//printf ta evabeo likhte partam
//printf("%d ",*(ptr+i));
}
printf("\n");
free( ptr );//jotogula jaiga niye kaj korlam shob free hoye gelo
return(0);
}
realloc():
malloc() বা calloc() দিয়ে মেমোরি দখল করেছেন কিন্তু পরে
বুঝছেন যে আপনার আরো মেমোরি দরকার,কিন্তু আগের দখল করা মেমোরির ডেটাগুলা সহ বা যাতে আগে দখল করা মেমোরির ডেটা মুছে না যায়, আগের গুলাও থাকবে এর সাথে আরেকটু জায়গা বাড়াতে চাচ্ছেন ঐ সময় realloc() ইউজ করব ।
এটা যেহেতু আগের মেমোরির সাথে নতুন ভাবে কিছু মেমোরি বাড়িয়ে
বা কমিয়ে দিচ্ছে তাই আগের মেমোরি লোকেশন যে পয়েন্টারের মধ্যে রেখেছিলেন ঐটাও পাস করা
লাগবে ।
realloc(*ptr , new_size) ; //new_size = নতুন কয়টা ব্লক লাগবে ঐটার সাইজ
free():
malloc() , calloc() , realloc() দিয়ে যত জায়গা দখল করেছিলেন
সবগুলা খালি করতে এটা ব্যবহার করা হয়,
free(ptr);
যেই পয়েন্টারের মধ্যে দখল করা জায়গার address ছিল ঐ পয়েন্টার
প্যারামিটার হিসেবে দিলেই ওই পয়েন্টার দিয়ে যতটুকু জায়গা দখল করেছিলেন খালি করে দিবে , দখল ছেড়ে দিবে ।
....................................................................................................................
*উপরের কোডে #include<'stdio.h> এর এইখানে ' extra inverted comma দিতে হইসে আমার, নাহলে ঐ লিখাটুক html code ভেবে প্রিন্ট হচ্ছিল না
scanf() এর ঐখানে & দিলাম না কেন?
উত্তরঃ কারণ আমরা যখন সাধারণ variable এ ইনপুট নেই তখন
int a;
scanf("%d",&a); মানে ইনপুট টা কোথায় store হবে ? address of 'a' তে
কিন্তু আমরা যখন পয়েন্টার নিয়ে কাজ করছি তখন পয়েন্টারে কি থাকে ?
address থাকে, তাই তখন আর & দিয়ে বুঝাইতে হয় না,
scanf("%d",ptr+iscanf("%d",ptr+i) // ptr+0 = 1000 , ptr+1 =1004 ,ptr+2 = 1008 এভাবে
তারপরও যদি & দিতে খুব মন চাই,
scanf("%d",&ptr[i]); // এটা মানে &ptr[i] পয়েন্টারের i তম index এর address এ store করে রাখো ।
আবার যেহেতে (ptr+i) এটার মধ্যে address থাকছে, তাই এর সামনে '*' সাইন দিলে এর ভ্যালু পেয়ে যাব আমরা ।ঐজন্যে
printf("%d ",*(ptr+i));
এভাবেও লিখতে পারছিলাম।
এইখানে এইটুকুই থাকবে, পরের পোষ্ট in sha Allah structure নিয়ে কিছু একটু লিখব ।


Comments
Post a Comment