সি মেমোরি ম্যানেজমেন্ট


90

আমি সবসময় শুনেছি যে সি তে আপনি কীভাবে মেমরি পরিচালনা করেন তা সত্যই আপনাকে দেখতে হবে। এবং আমি এখনও সি শিখতে শুরু করেছি, তবে এখনও পর্যন্ত, আমাকে সম্পর্কিত কোনও কাজ পরিচালনার কোনও স্মৃতিই করতে হয় নি .. আমি সবসময় ভেরিয়েবলগুলি প্রকাশ করতে এবং সমস্ত রকমের কুৎসিত কাজ করার চিন্তাভাবনা করি। তবে এটি মনে হয় না।

আপনি যখন কিছু "মেমরি ম্যানেজমেন্ট" করতে চান তখন কেউ আমাকে (কোড উদাহরণ সহ) একটি উদাহরণ দেখাতে পারে?


উত্তর:


231

দুটি স্থানে ভেরিয়েবলগুলি মেমরিতে রাখা যেতে পারে। আপনি যখন একটি ভেরিয়েবল তৈরি করেন:

int  a;
char c;
char d[16];

ভেরিয়েবলগুলি " স্ট্যাক " তৈরি করা হয়। স্ট্যাক ভেরিয়েবলগুলি সুযোগের বাইরে চলে গেলে স্বয়ংক্রিয়ভাবে মুক্ত হয় (অর্থাৎ কোডটি যখন তাদের কাছে পৌঁছাতে পারে না)। আপনি এগুলিকে "স্বয়ংক্রিয়" ভেরিয়েবল বলে শুনে থাকতে পারেন তবে এটি ফ্যাশনের বাইরে চলে গেছে।

অনেক শিক্ষানবিস উদাহরণ কেবল স্ট্যাক ভেরিয়েবল ব্যবহার করবে।

স্ট্যাকটি দুর্দান্ত কারণ এটি স্বয়ংক্রিয়। উদাহরণস্বরূপ: উইন্ডোজে, মাইক্রোসফ্ট লিঙ্কারের জন্য ডিফল্ট সেটিংসের আওতায় স্ট্যাকটি 1 এমবিতে সেট করা থাকে এবং এটি সমস্তই আপনার ভেরিয়েবলের জন্য উপলব্ধ নয়।

আপনার অ্যারে কত বড় তা সংকলনের সময় আপনি যদি না জানেন বা আপনার যদি বড় অ্যারে বা স্ট্রাক্ট দরকার হয় তবে আপনার "প্ল্যান বি" দরকার।

প্ল্যান বিকে " হিপ " বলা হয় । অপারেটিং সিস্টেমটি আপনাকে দেয় এমন আপনি সাধারণত ভেরিয়েবলগুলি তৈরি করতে পারেন তবে এটি আপনাকে নিজেই করতে হবে। আগের পোস্টিংগুলি আপনাকে এটি করতে পারে এমন এক উপায় আপনাকে দেখিয়েছিল, যদিও অন্যান্য উপায় রয়েছে:

int size;
// ...
// Set size to some value, based on information available at run-time. Then:
// ...
char *p = (char *)malloc(size);

(দ্রষ্টব্য যে গাদা মধ্যে চলকগুলি সরাসরি ম্যানিপুলেটেড হয় না, তবে পয়েন্টারগুলির মাধ্যমে)

একবার আপনি একটি হিপ ভেরিয়েবল তৈরি করলে, সমস্যাটি হ'ল কম্পাইলারটি এটি সম্পন্ন করার সময় আপনাকে বলতে পারে না, সুতরাং আপনি স্বয়ংক্রিয়ভাবে প্রকাশ হারাবেন। আপনি যে "ম্যানুয়াল রিলিজিং "টির কথা উল্লেখ করেছেন সেখানে এসেছেন Your আপনার কোডটি এখন ভেরিয়েবলের আর প্রয়োজন হয় না তা নির্ধারণ করার জন্য দায়বদ্ধ এবং এটিকে ছেড়ে দিন যাতে স্মৃতিটি অন্য উদ্দেশ্যে নেওয়া যেতে পারে। উপরের মামলার জন্য, সাথে:

free(p);

এই দ্বিতীয় বিকল্পটি "দুষ্টু ব্যবসায়" কী করে তা হ'ল যখন চলকটির আর প্রয়োজন হয় না তখন তা জানার পক্ষে সর্বদা সহজ নয়। যখন আপনার প্রয়োজন হয় না তখন কোনও ভেরিয়েবল প্রকাশ করতে ভুলে যা আপনার প্রোগ্রামটির প্রয়োজন এমন আরও মেমরি গ্রাস করে। এই অবস্থাকে "ফুটো" বলা হয়। "ফাঁস" মেমরিটি কোনও কিছুর জন্য ব্যবহার করা যাবে না যতক্ষণ না আপনার প্রোগ্রামটি শেষ হয় এবং ওএস এর সমস্ত সংস্থান পুনরুদ্ধার করে না। এমনকি নাস্তিরের সমস্যাগুলি সম্ভব যদি আপনি ভুলরূপে এটির কাজটি করার আগে ভুলভাবে একটি গাদা পরিবর্তনশীল প্রকাশ করেন release

সি এবং সি ++ এ আপনি উপরে দেখানো মত আপনার হিপ ভেরিয়েবলগুলি পরিষ্কার করতে দায়বদ্ধ। তবে জাভা এবং সি # এর মতো নেট ভাষা হিসাবে ভাষা এবং পরিবেশ রয়েছে যা আলাদা পদ্ধতির ব্যবহার করে, যেখানে গাদাটি নিজে থেকে পরিষ্কার হয়ে যায়। "আবর্জনা সংগ্রহ" নামে পরিচিত এই দ্বিতীয় পদ্ধতিটি বিকাশকারীদের পক্ষে অনেক সহজ তবে আপনি ওভারহেড এবং পারফরম্যান্সে একটি জরিমানা প্রদান করেন। এটি একটি ভারসাম্য।

(আমি একটি সহজ সরল দিতে অনেকগুলি বিবরণ দেখেছি তবে আশা করি আরও সমতল উত্তর)


4
আপনি যদি স্ট্যাকের উপরে কিছু রাখতে চান তবে কম্পাইল সময়ে এটি কতটা বড় তা জানেন না, বরাদ্দ () স্ট্যাক ফ্রেমকে রুম তৈরি করতে বাড়িয়ে দিতে পারে। কোনও ফ্রি () নেই, ফাংশনটি ফিরে আসার সময় পুরো স্ট্যাক ফ্রেমটি পপ হয়। বড় বরাদ্দের জন্য বরাদ্দ () ব্যবহার করা বিপদ পূর্ণ।
ডিজিন্ট্রি

4
হয়ত আপনি বৈশ্বিক ভেরিয়েবলগুলির মেমরি অবস্থান সম্পর্কে এক বা দুটি বাক্য যুক্ত করতে পারেন
মাইকেল কেফার

সি কখনো নিক্ষেপ বিনিময়ে malloc(), তার কারণ UB, (char *)malloc(size);দেখতে stackoverflow.com/questions/605845/...
EsmaeelE

17

এখানে একটি উদাহরণ। ধরুন আপনার একটি স্টার্ডআপ () ফাংশন রয়েছে যা একটি স্ট্রিংয়ের সদৃশ করে:

char *strdup(char *src)
{
    char * dest;
    dest = malloc(strlen(src) + 1);
    if (dest == NULL)
        abort();
    strcpy(dest, src);
    return dest;
}

এবং আপনি এটিকে এটি বলেছেন:

main()
{
    char *s;
    s = strdup("hello");
    printf("%s\n", s);
    s = strdup("world");
    printf("%s\n", s);
}

আপনি দেখতে পাচ্ছেন যে প্রোগ্রামটি কাজ করে, তবে আপনি এটিকে মুক্ত না করে মেমরি বরাদ্দ করেছেন (ম্যালোকের মাধ্যমে)। আপনি দ্বিতীয়বার স্টার্ডআপ ডাকলে আপনি আপনার পয়েন্টারটি প্রথম মেমোরি ব্লকের কাছে হারিয়ে ফেলেছেন।

এই অল্প পরিমাণ স্মৃতির জন্য এটি কোনও বড় কথা নয়, তবে কেসটি বিবেচনা করুন:

for (i = 0; i < 1000000000; ++i)  /* billion times */
    s = strdup("hello world");    /* 11 bytes */

আপনি এখন 11 গিগ মেমরি ব্যবহার করেছেন (সম্ভবত আরও বেশি, আপনার মেমোরি পরিচালকের উপর নির্ভর করে) এবং যদি আপনি ক্রাশ না করেন তবে আপনার প্রক্রিয়াটি সম্ভবত বেশ ধীরে চলছে running

ঠিক করার জন্য, ম্যালোক () ব্যবহার করে শেষ করার পরে প্রাপ্ত সমস্ত কিছুর জন্য আপনাকে ফ্রি () কল করতে হবে:

s = strdup("hello");
free(s);  /* now not leaking memory! */
s = strdup("world");
...

আশা করি এই উদাহরণটি সাহায্য করবে!


আমি এই উত্তরটি আরও ভাল পছন্দ করি। তবে আমি একটু পাশের প্রশ্ন পেয়েছি। আমি লাইব্রেরিগুলির সাথে সমাধান করার জন্য এই জাতীয় কোনও প্রত্যাশা করব, এমন কোনও লাইব্রেরি নেই যা মৌলিক ডেটাটাইপগুলি ঘনিষ্ঠভাবে অনুকরণ করে এবং তাদের সাথে মেমরি মুক্ত করার বৈশিষ্ট্য যুক্ত করে যাতে ভেরিয়েবলগুলি ব্যবহার করার পরে তারাও স্বয়ংক্রিয়ভাবে মুক্তি পায়?
লরেঞ্জো

কোনওটিই সেই মানটির অংশ নয়। আপনি যদি সি ++ এ যান তবে আপনি স্ট্রিং এবং পাত্রে পাবেন যা স্বয়ংক্রিয়ভাবে মেমরি পরিচালনা করে।
মার্ক হ্যারিসন

আমি দেখছি, তাই কিছু 3 য় পক্ষের libs আছে? আপনি তাদের নামকরণ করতে পারেন?
লোরেঞ্জো

9

আপনি যখন স্ট্যাকের পরিবর্তে গাদাটিতে মেমরি ব্যবহার করতে চান তখন আপনাকে "মেমরি ম্যানেজমেন্ট" করতে হবে। রানটাইম অবধি কোনও অ্যারে তৈরি করা কত বড় তা আপনি যদি না জানেন তবে আপনাকে গাদাটি ব্যবহার করতে হবে। উদাহরণস্বরূপ, আপনি স্ট্রিংয়ে কিছু সঞ্চয় করতে চাইতে পারেন তবে প্রোগ্রামটি চালা না হওয়া পর্যন্ত এর সামগ্রীগুলি কতটা বড় হবে তা জানেন না। সেক্ষেত্রে আপনি এই জাতীয় কিছু লিখবেন:

 char *string = malloc(stringlength); // stringlength is the number of bytes to allocate

 // Do something with the string...

 free(string); // Free the allocated memory

5

আমি মনে করি সি এর পয়েন্টারের ভূমিকা বিবেচনা করার জন্য প্রশ্নের উত্তর দেওয়ার সর্বাধিক সংক্ষিপ্ত উপায় হল পয়েন্টারটি একটি হালকা ও শক্তিশালী তবে শক্তিশালী প্রক্রিয়া যা আপনাকে পায়ে গুলি করার জন্য অপরিমেয় সামর্থ্যের ব্যয়ে অপরিসীম স্বাধীনতা দেয়।

সিতে আপনার পয়েন্টারগুলি আপনার নিজের স্মৃতিতে নির্দেশ করার বিষয়টি নিশ্চিত করার দায়িত্ব আপনার এবং আপনার একা। এটির জন্য একটি সংগঠিত এবং নিয়মানুবর্তিত পদ্ধতির প্রয়োজন, যদি না আপনি পয়েন্টারগুলি ত্যাগ করেন, যা কার্যকর সি লিখতে অসুবিধা সৃষ্টি করে which

তারিখের পোস্ট করা উত্তরগুলি স্বয়ংক্রিয় (স্ট্যাক) এবং হিপ ভেরিয়েবল বরাদ্দগুলিতে মনোনিবেশ করে। স্ট্যাক বরাদ্দ ব্যবহার করে স্বয়ংক্রিয়ভাবে পরিচালিত এবং সুবিধাজনক মেমরি তৈরি হয়, তবে কিছু পরিস্থিতিতে (বৃহত বাফার, পুনরাবৃত্ত আলগোরিদিম) এটি স্ট্যাকের ওভারফ্লোয়ের ভয়াবহ সমস্যার সৃষ্টি করতে পারে। স্ট্যাকের জন্য আপনি ঠিক কতটা মেমরি বরাদ্দ করতে পারবেন তা জানা সিস্টেমের উপর নির্ভর করে। কিছু এম্বেড থাকা পরিস্থিতিতে কয়েক ডজন বাইট আপনার সীমা হতে পারে, কিছু ডেস্কটপ পরিস্থিতিতে আপনি নিরাপদে মেগাবাইট ব্যবহার করতে পারেন।

গাদা বরাদ্দ ভাষা কম সহজাত হয়। এটি মূলত লাইব্রেরি কলগুলির একটি সেট যা আপনি ফিরে দেওয়ার জন্য প্রস্তুত না হওয়া অবধি প্রদত্ত আকারের মেমরির একটি ব্লকের মালিকানা মঞ্জুরি দেয় ('ফ্রি')। এটি সহজ শোনায়, তবে অনাবৃত প্রোগ্রামার শোকের সাথে যুক্ত। সমস্যাগুলি সহজ (একই মেমরিটি দু'বার মুক্ত করা, বা মোটেও নয় [মেমরি ফাঁস], পর্যাপ্ত মেমরি বরাদ্দ না করা [বাফার ওভারফ্লো] ইত্যাদি) তবে এড়ানো এবং ডিবাগ করা কঠিন। চিত্তাকর্ষক ক্ষেত্রে একটি hightly শৃঙ্খলাবদ্ধ পদ্ধতির একেবারে বাধ্যতামূলক তবে অবশ্যই ভাষা আসলে এটি ম্যান্ডেট করে না।

আমি অন্য ধরণের মেমরি বরাদ্দের উল্লেখ করতে চাই যা অন্যান্য পোস্টগুলি উপেক্ষা করে। কোনও ফাংশনের বাইরে ঘোষণা করে স্থিরভাবে ভেরিয়েবলগুলি বরাদ্দ করা সম্ভব। আমি মনে করি সাধারণভাবে এই জাতীয় বরাদ্দ একটি খারাপ র‌্যাপ পায় কারণ এটি বৈশ্বিক চলক দ্বারা ব্যবহৃত হয়। তবে কিছুই নেই যা বলেছে যে এইভাবে বরাদ্দ করা মেমরিটি ব্যবহারের একমাত্র উপায় স্প্যাগেটি কোডের জগতে একটি অদৃশ্য বৈশ্বিক পরিবর্তনশীল। স্থির বরাদ্দ পদ্ধতিটি গাদা এবং স্বয়ংক্রিয় বরাদ্দের পদ্ধতির কিছু সমস্যাগুলি এড়াতে কেবল ব্যবহার করা যেতে পারে। কিছু সি প্রোগ্রামার জেনে অবাক হয় যে বড় এবং পরিশীলিত সি এম্বেড এবং গেমস প্রোগ্রামগুলি হিপ বরাদ্দের কোনও ব্যবহার ছাড়াই নির্মিত হয়েছে।


4

মেমরি কীভাবে বরাদ্দ করা যায় এবং কীভাবে মুক্ত করা যায় সে সম্পর্কে এখানে কিছু দুর্দান্ত উত্তর রয়েছে এবং আমার মতে সি ব্যবহারের আরও চ্যালেঞ্জিং দিকটি নিশ্চিত করছে যে আপনি যে একমাত্র মেমরি ব্যবহার করছেন তা আপনার বরাদ্দ করা মেমরি - এটি যদি আপনি শেষ করেন তবে সঠিকভাবে না করা হয় এই সাইটের কাজিন - একটি বাফার ওভারফ্লো - এবং আপনি খুব অপ্রত্যাশিত ফলাফল সহ অন্য অ্যাপ্লিকেশন দ্বারা ব্যবহৃত হচ্ছে মেমরির ওভাররাইট করা হতে পারে।

একটি উদাহরণ:

int main() {
    char* myString = (char*)malloc(5*sizeof(char));
    myString = "abcd";
}

এই মুহুর্তে আপনি মাইস্ট্রিংয়ের জন্য 5 বাইট বরাদ্দ করেছেন এবং এটিকে "abcd \ 0" দিয়ে ভরাট করেছেন (স্ট্রিংগুলি নালিতে শেষ হয় - \ 0)। যদি আপনার স্ট্রিং বরাদ্দ ছিল

myString = "abcde";

আপনি আপনার প্রোগ্রামে বরাদ্দকৃত 5 টি বাইটে "অ্যাবিসিডি" বরাদ্দ করবেন, এবং শেষের নাল অক্ষরটি এর শেষে দেওয়া হবে - মেমোরির একটি অংশ যা আপনার ব্যবহারের জন্য বরাদ্দ করা হয়নি এবং হতে পারে নিখরচায়, তবে অন্য অ্যাপ্লিকেশন দ্বারা সমানভাবে ব্যবহৃত হতে পারে - এটি মেমরি পরিচালনার গুরুত্বপূর্ণ অংশ, যেখানে কোনও ভুলের অপ্রত্যাশিত (এবং কখনও কখনও অপূরণীয়) পরিণতিও ঘটতে পারে।


এখানে আপনি 5 বাইট বরাদ্দ। পয়েন্টার বরাদ্দ করে এটি আলগা করুন। এই পয়েন্টারটিকে মুক্ত করার যে কোনও প্রচেষ্টা অনির্ধারিত আচরণের দিকে পরিচালিত করে। দ্রষ্টব্য সি-স্ট্রিংগুলি কোনও অপারেটর নেই = অপারেটরকে ওভারলোড করে না।
মার্টিন ইয়র্ক

যদিও, এটি আপনি যে ম্যালোকটি ব্যবহার করছেন তার উপর সত্যই নির্ভর করে। অনেক ম্যালোক অপারেটর 8 বাইটে সারিবদ্ধ হন। সুতরাং এই ম্যালোকটি যদি শিরোনাম / পাদচরণ ব্যবস্থা ব্যবহার করে তবে ম্যালোক 5 + 4 * 2 (উভয় শিরোলেখ এবং পাদচরণের জন্য 4 বাইট) সংরক্ষণ করবে। এটি 13 বাইট হবে এবং ম্যালোক আপনাকে প্রান্তিককরণের জন্য কেবল একটি অতিরিক্ত 3 বাইট দেবে। আমি এটি বলছি না যে এটি ব্যবহার করা ভাল ধারণা, কারণ এটি কেবলমাত্র এমন সিস্টেমগুলিই করবে যার ম্যালোক এই জাতীয়ভাবে কাজ করে, তবে কেন কোনও ভুল কাজ করা কার্যকর হতে পারে তা জানা অন্তত গুরুত্বপূর্ণ।
কোডাই

লোকি: আমি strcpy()পরিবর্তে ব্যবহারের উত্তর সম্পাদনা করেছি =; আমি ধরে নিই যে ক্রিস বিসি এর উদ্দেশ্য ছিল।
ইক্রিস্টোফারসন

আমি বিশ্বাস করি আধুনিক প্ল্যাটফর্মগুলিতে হার্ডওয়্যার মেমরি সুরক্ষা ব্যবহারকারীর স্পেস প্রক্রিয়াগুলিকে অন্য প্রক্রিয়াগুলির ঠিকানা স্থানগুলিকে ওভাররাইট করা থেকে বিরত করে; পরিবর্তে আপনি একটি সেগমেন্টেশন ত্রুটি পেতে চাই। তবে এটি প্রতি সে সি এর অংশ নয়।
ইক্রিস্টোফারসন

4

মনে রাখার মতো একটি জিনিস হ'ল আপনার পয়েন্টারগুলিকে NUL এ সর্বদা সূচনা করা, যেহেতু একটি অবিশ্রুত পয়েন্টারে সিউডোরডম বৈধ মেমরি ঠিকানা থাকতে পারে যা পয়েন্টার ত্রুটিগুলি নিঃশব্দে এগিয়ে যেতে পারে। NULL দিয়ে সূচনা করার জন্য কোনও পয়েন্টারকে জোর করে, আপনি এই পয়েন্টারটি আরম্ভ না করেই ব্যবহার করছেন কিনা তা আপনি সর্বদা ধরতে পারেন। কারণটি হ'ল অপারেটিং সিস্টেমগুলি নাল পয়েন্টার ব্যবহারের ফাঁদে ফেলতে সাধারণ সুরক্ষা ব্যতিক্রমগুলিতে ভার্চুয়াল ঠিকানা 0x0000000000 "তার" করে।


2

এছাড়াও আপনি যখন একটি বিশাল অ্যারে সংজ্ঞা দিতে চান তখন আপনি গতিশীল মেমরি বরাদ্দ ব্যবহার করতে চাইতে পারেন, ইনট [10000] বলুন। আপনি এটিকে কেবল স্ট্যাকের মধ্যে রাখতে পারবেন না কারণ, এইচ এম ... আপনি একটি স্ট্যাকের ওভারফ্লো পাবেন।

লিঙ্কযুক্ত তালিকা বা বাইনারি ট্রি বলুন, অন্য একটি ভাল উদাহরণ কোনও ডাটা স্ট্রাকচারের বাস্তবায়ন। এখানে পেস্ট করার জন্য আমার কাছে নমুনা কোড নেই তবে আপনি এটি সহজে গুগল করতে পারেন।


2

(আমি লিখছি কারণ আমি এখনও পর্যন্ত উত্তরগুলি যথেষ্ট চিহ্নে নেই বলে মনে করি feel)

আপনার মেমরি পরিচালনার উল্লেখযোগ্য কারণ হ'ল আপনার যখন কোনও সমস্যা / সমাধান হয় তখন আপনার জটিল কাঠামো তৈরি করা দরকার। (যদি আপনি যদি স্ট্যাকের একসাথে অনেক বেশি জায়গা বরাদ্দ করেন তবে যদি আপনার প্রোগ্রামগুলি ক্র্যাশ হয়ে থাকে তবে এটি একটি বাগ)) সাধারণত, আপনার প্রথম ডেটা কাঠামোটি শিখতে হবে তা হল এক ধরণের তালিকা । এখানে আমার মাথার উপরের অংশে একটি যুক্ত লিঙ্ক রয়েছে:

typedef struct listelem { struct listelem *next; void *data;} listelem;

listelem * create(void * data)
{
   listelem *p = calloc(1, sizeof(listelem));
   if(p) p->data = data;
   return p;
}

listelem * delete(listelem * p)
{
   listelem next = p->next;
   free(p);
   return next;
}

void deleteall(listelem * p)
{
  while(p) p = delete(p);
}

void foreach(listelem * p, void (*fun)(void *data) )
{
  for( ; p != NULL; p = p->next) fun(p->data);
}

listelem * merge(listelem *p, listelem *q)
{
  while(p != NULL && p->next != NULL) p = p->next;
  if(p) {
    p->next = q;
    return p;
  } else
    return q;
}

স্বাভাবিকভাবেই, আপনি কয়েকটি অন্যান্য ফাংশন চান, তবে মূলত, এটি আপনার মেমরি পরিচালনার জন্য প্রয়োজন। আমার উল্লেখ করা উচিত যে "ম্যানুয়াল" মেমরির পরিচালনার সাহায্যে এমন কয়েকটি কৌশল রয়েছে যা উদাহরণস্বরূপ,

  • সত্য যে ব্যবহার যদি malloc 4 দ্বারা একটি পয়েন্টার বিভাজ্য ফিরে যাওয়ার (ভাষা মান দ্বারা) নিশ্চিত করা হয়,
  • নিজের কিছু দুষ্টু উদ্দেশ্যতে অতিরিক্ত জায়গা বরাদ্দ করা,
  • মেমরি পুল তৈরি ..

একটি ভাল ডিবাগার পান ... শুভকামনা!


তথ্য-কাঠামো শেখা মেমরি পরিচালনা বোঝার পরবর্তী মূল পদক্ষেপ। এই কাঠামোগুলি যথাযথভাবে চালানোর জন্য অ্যালগরিদমগুলি শিখলে আপনি এই আঘাতগুলি কাটিয়ে উঠতে উপযুক্ত পদ্ধতিগুলি দেখায়। এজন্য আপনি একই কোর্সে শেখানো ডেটা-স্ট্রাকচার এবং অ্যালগরিদমগুলি খুঁজে পাবেন।
aj.toulan

0

@ ইউরো মিশেল্লি

যুক্ত করার জন্য একটি নেতিবাচক হ'ল ফাংশনটি ফিরে আসার পরে স্ট্যাকের পয়েন্টারগুলি বৈধ থাকে না, সুতরাং আপনি কোনও ফাংশন থেকে স্ট্যাক ভেরিয়েবলটিতে কোনও পয়েন্টারটি ফেরত দিতে পারবেন না। এটি একটি সাধারণ ত্রুটি এবং একটি বড় কারণ যা আপনি কেবল স্ট্যাক ভেরিয়েবলের মাধ্যমে পেতে পারেন না। যদি আপনার ফাংশনটিতে কোনও পয়েন্টার ফেরতের দরকার হয়, তবে আপনাকে মেমোরি ম্যানেজমেন্টের সাথে ম্যালোক করতে হবে এবং ডিল করতে হবে।


0

@ টেড পার্সিভাল :
... আপনাকে ম্যালোক () এর রিটার্ন মান দিতে হবে না।

আপনি অবশ্যই সঠিক। আমি বিশ্বাস করি যে এটি সর্বদা সত্য ছিল, যদিও আমার কাছে চেক করার জন্য কেঅ্যান্ডআর এর একটি অনুলিপি নেই ।

আমি সি-তে অনেকগুলি অন্তর্নিহিত রূপান্তর পছন্দ করি না, তাই "জাদু" আরও দৃশ্যমান করার জন্য আমি ক্যাসেটগুলি ব্যবহার করার প্রবণতা রাখি। কখনও কখনও এটি পাঠযোগ্যতায় সহায়তা করে, কখনও কখনও তা করে না এবং কখনও কখনও এটি একটি নীরব ত্রুটি সংকলক দ্বারা ধরা পড়ে causes তবুও, আমার একথা বা অন্য কোনও বিষয়ে দৃ have় মতামত নেই।

এটি বিশেষত সম্ভবত যদি আপনার সংকলক সি ++ - স্টাইলের মন্তব্যগুলি বোঝে।

হ্যাঁ ... আপনি আমাকে সেখানে ধরেছেন। আমি সি +++ এর চেয়ে অনেক বেশি সময় সি'র চেয়ে ব্যয় করি Thanks


@ ক্রিস্টোফারসন, ধন্যবাদ আপনি ঠিক বলেছেন - তবে দয়া করে মনে রাখবেন যে স্টক ওভারফ্লো এমনকি পাবলিক বিটাতে আসার আগে এই প্রশ্নোত্তরটি আগস্ট ২০০৮ থেকে ছিল। তারপরে, আমরা কীভাবে সাইটটির কাজ করা উচিত তা নির্ধারণ করছিলাম। এই প্রশ্ন / উত্তরের বিন্যাসটি অগত্যা কীভাবে এসও ব্যবহার করতে হবে তার মডেল হিসাবে দেখা উচিত নয়। ধন্যবাদ!
ইউরো মিশেল্লি

আহ, এটি দেখানোর জন্য ধন্যবাদ - আমি বুঝতে পারি নি যে সাইটের দিকটি তখনও প্রবাহিত ছিল।
ইক্রিস্টোফারসন

0

সি তে, আপনার কাছে দুটি ভিন্ন পছন্দ আছে। এক, আপনি সিস্টেমটিকে আপনার জন্য মেমরিটি পরিচালনা করতে দিতে পারেন। বিকল্পভাবে, আপনি নিজের দ্বারা এটি করতে পারেন। সাধারণত, আপনি যতক্ষণ সম্ভব পূর্বের সাথে লেগে থাকতে চাইবেন। তবে সি-তে স্বয়ংক্রিয়ভাবে পরিচালিত মেমরিটি অত্যন্ত সীমাবদ্ধ এবং আপনাকে অনেক ক্ষেত্রে ম্যানুয়ালি ম্যানুয়ালি পরিচালনা করতে হবে যেমন:

ক। আপনি ভেরিয়েবলটি ফাংশনগুলি আউটলাইভ করতে চান এবং আপনি বৈশ্বিক চলক রাখতে চান না। প্রাক্তন:

কাঠামো জোড়া {
   ইন্ট ভাল;
   কাঠামো জোড়া * পরবর্তী;
}

কাঠামো জোড়া * new_pair (int val) {
   কাঠামো জোড়া * এনপি = ম্যালোক (আকারের (কাঠামো জোড়া));
   np-> ভাল = ভাল;
   np-> পরের = NULL;
   রিটার্ন এনপি;
}

খ। আপনি গতিশীল মেমরি বরাদ্দ করতে চান। সর্বাধিক সাধারণ উদাহরণ নির্দিষ্ট দৈর্ঘ্য ছাড়াই অ্যারে হয়:

ইন্ট * মাই_স্পেশাল_আরে;
মাই_স্পেশাল_আরে = ম্যালোক (আকারের (ইনট) * নাম্বার_অফলেট);
(i = 0; i) এর জন্য

গ। আপনি সত্যিই নোংরা কিছু করতে চান। উদাহরণস্বরূপ, আমি অনেক ধরণের ডেটা উপস্থাপন করার জন্য একটি কাঠামো চাই এবং আমি ইউনিয়ন পছন্দ করি না (ইউনিয়নটি খুব অগোছালো দেখাচ্ছে):

কাঠামোগত তথ্য int ডেটা_ টাইপ; দীর্ঘ ডেটা_ইন_মীম; }; কাঠামো প্রাণী {/ * কিছু * /}; কাঠামো ব্যক্তি {/ * অন্য কিছু জিনিস * /}; কাঠামো প্রাণী * পড়ুন_নিমাল (); কাঠামোযুক্ত ব্যক্তি * read_Press (); / * প্রধানত * / কাঠামোর ডেটা নমুনা; sampe.data_type = ইনপুট_ টাইপ; স্যুইচ (ইনপুট_প্রকার) { কেস ডেটা_প্রেসন: নমুনা.ডাটা_ইন_মেম = পঠন_পোষক (); বিরতি; কেস ডেটা_আনিমাল: নমুনা.ডাটা_ইন_মেম = পঠন_নিমাল (); ডিফল্ট: প্রিন্টফ ("ওহহহ! আমি আপনাকে সতর্ক করে দিয়েছি, এটি আবার এবং আমি আপনার ওএসকে ত্রুটিযুক্ত করব"); }

দেখুন, কিছু দীর্ঘ ধরে রাখার জন্য একটি দীর্ঘ মান যথেষ্ট। এটিকে মুক্ত করতে কেবল মনে রাখবেন, অথবা আপনি আফসোস করবেন। সি: ডি তে মজা করার জন্য এটি আমার প্রিয় কৌশলগুলির মধ্যে একটি।

তবে, সাধারণত, আপনি আপনার প্রিয় কৌশলগুলি (T___T) থেকে দূরে থাকতে চান। আপনি যদি খুব বেশি ঘন ঘন ব্যবহার করেন তবে তাড়াতাড়ি বা পরে আপনার ওএসটি ভেঙে ফেলবেন। যতক্ষণ না আপনি * বরাদ্দ এবং বিনামূল্যে ব্যবহার করবেন না ততক্ষণ এটি নিরাপদ যে আপনি এখনও ভার্জিন, এবং কোডটি এখনও দুর্দান্ত দেখাচ্ছে।


"দেখুন, কিছু ধরে রাখার জন্য একটি দীর্ঘ মান যথেষ্ট" -: / আপনি কী সম্পর্কে কথা বলছেন, বেশিরভাগ সিস্টেমে একটি দীর্ঘ মান 4 বাইট হয়, এটি কোনও ইন্টির মতোই। এখানে পয়েন্টারগুলির সাথে এটি ফিট করার একমাত্র কারণ হ'ল দীর্ঘ আকারটি পয়েন্টারের আকারের সাথে একই রকম হয়। যদিও আপনার সত্যিকার অর্থে শূন্য * ব্যবহার করা উচিত।
স্কোর_উন্ডারে

-2

অবশ্যই যদি আপনি এমন কোনও অবজেক্ট তৈরি করেন যা আপনি এটি ব্যবহার করার সুযোগের বাইরে বিদ্যমান থাকেন তবে এখানে একটি স্বীকৃত উদাহরণ রয়েছে (মনে রাখবেন যে আমার বাক্য গঠনটি বন্ধ হয়ে যাবে; আমার সিটি মরিচা, তবে এই উদাহরণটি এখনও ধারণাটি চিত্রিত করবে):

class MyClass
{
   SomeOtherClass *myObject;

   public MyClass()
   {
      //The object is created when the class is constructed
      myObject = (SomeOtherClass*)malloc(sizeof(myObject));
   }

   public ~MyClass()
   {
      //The class is destructed
      //If you don't free the object here, you leak memory
      free(myObject);
   }

   public void SomeMemberFunction()
   {
      //Some use of the object
      myObject->SomeOperation();
   }


};

এই উদাহরণস্বরূপ, আমি মাইক্র্লাসের জীবদ্দশায় সামোথারক্লাস টাইপের একটি অবজেক্ট ব্যবহার করছি। স্যোমোথার ক্লাস অবজেক্টটি বেশ কয়েকটি ফাংশনে ব্যবহৃত হয়, তাই আমি মেমরিটিকে গতিশীলভাবে বরাদ্দ করেছি: মাই ক্লাস তৈরি হয়ে গেলে, বস্তুর জীবনজুড়ে বেশ কয়েকবার ব্যবহৃত হয় এবং তারপরে মাইক্লাসটি মুক্ত হয়ে গেলে সিমোথার ক্লাস অবজেক্টটি তৈরি হয়।

স্পষ্টতই যদি এটি আসল কোড হয় তবে এইভাবে মাইবজেক্টটি তৈরি করার কোনও কারণ নেই (সম্ভবত মেমরির স্ট্যাককে বাদ দিয়ে) তবে এই ধরণের অবজেক্ট তৈরি / ধ্বংস কার্যকর হবে যখন আপনার অনেকগুলি অবজেক্ট থাকে এবং আপনি সূক্ষ্মভাবে নিয়ন্ত্রণ করতে চান যখন সেগুলি তৈরি এবং ধ্বংস হয় (যাতে আপনার অ্যাপ্লিকেশনটি পুরো জীবনকালের জন্য 1 গিগাবাইট র‌্যাম চুষে না ফেলে, উদাহরণস্বরূপ) এবং উইন্ডোড পরিবেশে, আপনি তৈরি করা বস্তু হিসাবে এটি বেশ বাধ্যতামূলক (বোতাম, বলুন) , কোনও নির্দিষ্ট ফাংশনের (বা এমনকি শ্রেণী ') স্কোপের বাইরে খুব ভাল উপস্থিত থাকা প্রয়োজন।


4
হেই, হ্যাঁ, এটা সি ++ না? আশ্চর্যজনক যে কেউ আমাকে এতে কল করতে পাঁচ মাস সময় লেগেছে।
TheSmurf
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.