Skip to main content

Dynamic Memory Allocation (Data Structure)

 



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));

 malloc() void টাইপের address রিটার্ন করে ,যেটাকে আমরা পয়েন্টারের মধ্যে store করে রাখতে চাচ্ছি , কার মধ্যে রাখতে চাচ্ছি ? পয়েন্টারের,

এইজন্যই টাইপ কাস্টিং এর সময় আমরা শুধু (int) এভাবে না লিখে (int*) এভাবে লিখছি এইখানে । এটার মাধ্যমে  আমরা malloc() কে বুঝিয়ে দিচ্ছি যে হ্যাঁ ভাই এটা ইন্টিজার ডেটা টাইপ না, এটা ইন্টিজার টাইপের পয়েন্টার , আপনি address দেন, আমরা রাখতে পারব । 


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+i

scanf("%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 নিয়ে কিছু একটু লিখব । 



previous

....

<- Pointer        



Comments

Popular posts from this blog

IELTS Spoken Class Adminssion Scenario - 01

.......  Student: Hello, May I come in, sir ? Optional (student): May I sit ? Sir:  Please have a seat. Sir: How may I help you, Sir ? Student: I would like to admit in your spoken course. Sir: Oh sure. Student: How many days are there in a week ? Sir: There are three classes in a week. Student: What time do you offer class ? Sir: We have class at 11am / 4pm / 6pm / 8pm

Php Learning Time

 Differences of explode( ) and implode( ) in php: explode: একটা স্ট্রিংকে কোনো একটা সেপারেটরের বেসিসে অ্যারেতে কনভার্ট করে, যেমন  <?php $text="Hello How are you?"; print_r(explode(" ",$text)); ?> This will give output of  Array (     [0] => Hello     [1] => How     [2] => are     [3] => you? ) Differences of array_splice( ) and array_slice( ) ধরেন আসল অ্যারে হচ্ছে    $arr =[ "Hello" , "this" , "is" , "test" , "text" ];    এখন এটাকে স্লাইসিং করার জন্য আমরা উপরের দুইটা মেথড ই ব্যবহার করতে পারি , কিন্তু array_splice এটা ইউজ করলে অরজিনাল array ও চেঞ্জ হয়ে যাবে, মানে যদি আমরা এভাবে লিখি  $var2 = array_splice ( $arr , 0 , 2 );   তাইলে $var2 এর ভিতরে থাকবে ["Hello" , "this"] ,  আর অরজিনাল array তে বাকি থাকবে ["is", "test", "text"] কিন্তু যদি আমরা ইউজ করি তাহলে অরজিনাল array আগের মতোই থাকবে পাশাপাশি $var2 এর মধ্যে ভ্যালু গুলা এসে পড়বে  Array (     [0] => ...