নাল মানগুলি কোথায় সংরক্ষণ করা হয়, বা সেগুলি আদৌ সংরক্ষণ করা হয়?


39

আমি নাল মান বা নাল রেফারেন্স সম্পর্কে জানতে চাই।

উদাহরণস্বরূপ আমার কাছে অ্যাপল নামে একটি ক্লাস রয়েছে এবং আমি এটির একটি উদাহরণ তৈরি করেছি।

Apple myApple = new Apple("yummy"); // The data is stored in memory

তারপরে আমি সেই আপেলটি খেয়েছি এবং এখন এটি নাল হওয়া দরকার, তাই আমি এটিকে নাল হিসাবে সেট করি।

myApple = null;

এই কল করার পরে, আমি ভুলে গিয়েছিলাম যে আমি এটি খেয়েছি এবং এখন চেক করতে চাই।

bool isEaten = (myApple == null);

এই কলটির সাথে, আমার অ্যাপল রেফারেন্সিংটি কোথায়? নাল কি একটি বিশেষ পয়েন্টারের মান? যদি তাই হয় তবে আমার কাছে যদি 1000 নাল অবজেক্ট থাকে তবে তারা যদি 1000 পয়েন্টার টাইপ হিসাবে ইন্ট্রি হিসাবে মনে করেন তবে তারা 1000 টি অবজেক্ট মেমরি স্পেস বা 1000 ইন মেমরি স্পেস দখল করে?

উত্তর:


45

আপনার উদাহরণে myAppleবিশেষ মান রয়েছে null(সাধারণত সমস্ত শূন্য বিট) এবং তাই কিছুই উল্লেখ করা হয় না। এটি যে বস্তুটিকে মূলত উল্লেখ করেছিল তা এখন গাদা হয়ে গেছে। এর অবস্থানটি পুনরুদ্ধার করার কোনও উপায় নেই। এটি আবর্জনা সংগ্রহ ছাড়াই সিস্টেমে মেমরি ফাঁস হিসাবে পরিচিত।

আপনি যদি প্রাথমিকভাবে 1000 টি রেফারেন্স নালায় সেট করে থাকেন তবে আপনার কাছে কেবল 1000 রেফারেন্সের জন্য জায়গা রয়েছে, সাধারণত 1000 * 4 বাইট (32-বিট সিস্টেমে, 64 এর চেয়ে দ্বিগুণ)। যদি এই 1000 টি উল্লেখগুলি মূলত সত্যিকারের বস্তুগুলিতে নির্দেশিত হয়, তবে আপনি প্রতিটি বস্তুর আকারের 1000 গুণ, এবং 1000 রেফারেন্সের জন্য স্থান বরাদ্দ করেছেন।

কিছু ভাষায় (যেমন সি এবং সি ++ এর মতো), পয়েন্টারগুলি সর্বদা কোনও কিছুর প্রতি নির্দেশ দেয় এমনকি "অবিচ্ছিন্ন" হলেও। তারা হ'ল ঠিকানাটি আপনার প্রোগ্রামটির অ্যাক্সেসের জন্য আইনী কিনা তা সমস্যা। বিশেষ ঠিকানা শূন্য (ওরফে null) ইচ্ছাকৃতভাবে আপনার ঠিকানার জায়গায় ম্যাপ করা হয়নি, সুতরাং মেমরি পরিচালনা ইউনিট (এমএমইউ) দ্বারা অ্যাক্সেস পাওয়া গেলে এবং আপনার প্রোগ্রামটি ক্র্যাশ হয়ে গেলে সেগমেন্টেশন ত্রুটি তৈরি হয়। কিন্তু যেহেতু ঠিকানা শূন্য ইচ্ছাকৃতভাবে করা হয় না এ ম্যাপ করা, এটি একটি আদর্শ মান নির্দেশ করে একটি পয়েন্টার, অত: পর তার ভূমিকা না কিছু ইশারা ব্যবহার করতে হয়ে null। গল্পটি সম্পূর্ণ করতে, আপনি যেমন newবা দিয়ে মেমরি বরাদ্দ করেনmalloc(), অপারেটিং সিস্টেমটি আপনার ঠিকানা জায়গায় র্যামের পৃষ্ঠাগুলি ম্যাপ করতে এমএমইউ কনফিগার করে এবং সেগুলি ব্যবহারযোগ্য হয় able এখনও ঠিকানার জায়গার বিস্তৃত পরিসীমা রয়েছে যা ম্যাপ করা হয়নি এবং সুতরাং সেগমেন্টেশন ত্রুটিগুলিও নিয়ে যায়।


খুব ভাল ব্যাখ্যা।
NoChance

6
"মেমরি ফাঁস" অংশে এটি কিছুটা ভুল। এটি স্বয়ংক্রিয় মেমরি পরিচালনা ছাড়াই সিস্টেমে একটি মেমরি ফাঁস। তবে, স্বয়ংক্রিয় মেমরি পরিচালনা প্রয়োগের জিসি একমাত্র সম্ভাব্য উপায় নয়। সি ++ এর std::shared_ptr<Apple>এমন একটি উদাহরণ যা জিসি বা Appleশূন্যের পরে ফাঁস হয় না ।
এমসাল্টাররা

1
@ এসএমএলটার্স - shared_ptrআবর্জনা সংগ্রহের জন্য কি কেবল একটি প্রাথমিক ফর্ম নয় ? জিসির কোনও আলাদা "আবর্জনা সংগ্রহকারী" থাকার দরকার নেই, কেবলমাত্র আবর্জনা সংগ্রহ ঘটে।
মনিকা

5
@ ব্রেন্ডন: "আবর্জনা সংগ্রহ" শব্দটি প্রায় সর্বজনীনভাবে বোঝা যায় যে নন-ডিসট্রিমেন্টিক সংগ্রহকে বোঝায় যা সাধারণ কোডের পথ থেকে পৃথক হয়ে যায়। রেফারেন্স গণনার উপর ভিত্তি করে নির্ধারক ধ্বংস সম্পূর্ণ আলাদা কিছু something
ম্যাসন হুইলার

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

13

উত্তরটি আপনি যে ভাষাটি ব্যবহার করছেন তার উপর নির্ভর করে।

সি / সি ++

সি এবং সি ++-তে, মূলশব্দটি NULL ছিল এবং NULL আসলে 0 ছিল 0. এটি সিদ্ধান্ত নেওয়া হয়েছিল যে "0x0000" কখনই কোনও অবজেক্টের জন্য বৈধ পয়েন্টার হতে পারে না এবং তাই এটিই সেই মানটি যা নির্দেশ করে এটি নির্ধারিত হয় একটি বৈধ পয়েন্টার নয়। তবে এটি সম্পূর্ণ নির্বিচারে। যদি আপনি এটি কোনও পয়েন্টারের মতো অ্যাক্সেস করার চেষ্টা করে থাকেন তবে এটি ঠিক এমন কোনও বস্তুর সাথে পয়েন্টারের মতো আচরণ করবে যা স্মৃতিতে আর বিদ্যমান নেই, যার ফলে একটি অবৈধ পয়েন্টার ব্যতিক্রম ছুঁড়ে দেওয়া হবে। পয়েন্টার নিজেই মেমরি দখল করে তবে কোনও পূর্ণসংখ্যার বস্তুর চেয়ে বেশি কিছু না। সুতরাং, আপনার যদি 1000 নাল পয়েন্টার থাকে তবে এটি 1000 পূর্ণসংখ্যার সমতুল্য। যদি সেই পয়েন্টারগুলির মধ্যে কিছু বৈধ অবজেক্টগুলিতে নির্দেশ করে তবে মেমরির ব্যবহারটি 1000 পূর্ণসংখ্যার সমতুল্য এবং সেইগুলি বৈধ পয়েন্টারগুলিতে থাকা মেমরির সমতুল্য হবে। মনে রাখবেন যে সি বা সি ++ এ,বোঝানো হয় না মেমোরি প্রকাশ করা হয়েছে, সুতরাং আপনাকে অবশ্যই স্পষ্টভাবে ডিলালোক (সি) ব্যবহার করে সেই বস্তুটি মুছতে হবে বা মুছে ফেলতে হবে (সি ++)।

জাভা

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


9
আপনার পার্থক্যটি সঠিক নয়: বাস্তবে, সি এবং সি ++ এ নাল পয়েন্টারটি মোটেও মেমরি ঠিকানার দিকে 0 দেখানোর দরকার নেই (যদিও এটি প্রাকৃতিক বাস্তবায়ন, জাভা এবং সি # এর মতোই)। এটি আক্ষরিক যে কোনও জায়গায় নির্দেশ করতে পারে। আক্ষরিক -0 স্পষ্টভাবে একটি নাল পয়েন্টারে রূপান্তর করা যায় এই বিষয়টি দ্বারা এটি কিছুটা বিস্মিত হয়। নাল পয়েন্টারের জন্য সঞ্চিত বিট প্যাটার্নটিতে এখনও সমস্ত শূন্যের দরকার নেই।
কনরাড রুডল্ফ

1
না তুমি ভুল. শব্দার্থবিদ্যা সম্পূর্ণরূপে স্বচ্ছ হয় ... প্রোগ্রাম, নাল পয়েন্টার এবং ম্যাক্রো মধ্যে NULL( না একটি শব্দ, উপায় দ্বারা) চিকিত্সা করা হয় যেন তারা জিরো-বিট ছিল। কিন্তু তারা যেমন প্রয়োগ করা প্রয়োজন হবে না, এবং সত্য কিছু অস্পষ্ট বাস্তবায়নের না ব্যবহার নন-জিরো নাল পয়েন্টার। আমি যদি লিখি if (myptr == 0)তবে সংকলকটি সঠিক কাজ করবে, নাল পয়েন্টারটি অভ্যন্তরীণভাবে উপস্থাপিত হলেও 0xabcdef
কনরাড রুডল্ফ

3
@ নীল: একটি নাল পয়েন্টার ধ্রুবক (শূন্যকে মূল্যায়ন করে পূর্ণসংখ্যার ধরণের ধাপ) একটি নাল পয়েন্টার মানে রূপান্তরিত । (.4.10 C ++ 11।) একটি নাল পয়েন্টার মানটি সমস্ত বিট শূন্যের গ্যারান্টিযুক্ত নয়। 0নাল পয়েন্টার ধ্রুবক, তবে এর অর্থ এই নয় যে myptr == 0সমস্ত বিট myptrশূন্য কিনা তা পরীক্ষা করে cks
মাদুর

5
@ নীল: আপনি সি
এফএকিউ

1
@ নীল এই কারণেই আমি NULLম্যাক্রোর উল্লেখ না করে বরং "নাল পয়েন্টার" সম্পর্কে কথা বলার এবং স্পষ্টভাবে উল্লেখ করেছিলাম যে "আক্ষরিক -0 স্পষ্টভাবে নাল পয়েন্টারে রূপান্তরিত হতে পারে"।
কনরাড রুডল্ফ

5

একটি পয়েন্টারটি কেবল একটি পরিবর্তনশীল যা বেশিরভাগ পূর্ণসংখ্যার ধরণের। এটি একটি মেমরি ঠিকানা নির্দিষ্ট করে যেখানে প্রকৃত অবজেক্টটি সংরক্ষণ করা হয়।

বেশিরভাগ ভাষা এই পয়েন্টার ভেরিয়েবলের মাধ্যমে অবজেক্ট সদস্যদের অ্যাক্সেসের অনুমতি দেয়:

int localInt = myApple.appleInt;

সংকলক একটি এর সদস্যদের অ্যাক্সেস করতে জানে Apple। এটি নির্দেশকের myAppleঠিকানার "অনুসরণ করে" এবং এর মান পুনরুদ্ধার করেappleInt

যদি আপনি একটি পয়েন্টার ভেরিয়েবলের নাল পয়েন্টারটি বরাদ্দ করেন তবে আপনি বিন্দু বিন্দুটিকে কোনও মেমরি ঠিকানায় পরিণত করবেন না। (যা সদস্যদের অ্যাক্সেসকে অসম্ভব করে তোলে))

প্রতিটি পয়েন্টারের জন্য আপনাকে মেমরির ঠিকানা পূর্ণসংখ্যার মান ধরে রাখতে হবে (বেশিরভাগ 32 বিট সিস্টেমে 4 বাইট, 64 বিট সিস্টেমে 8 বাইট)। এটি নাল পয়েন্টারগুলির ক্ষেত্রেও সত্য।


আমি মনে করি রেফারেন্স ভেরিয়েবল / অবজেক্টগুলি হুবহু পয়েন্টার নয়। আপনি যদি এগুলি মুদ্রণ করেন তবে তাদের মধ্যে ক্লাসনাম @ হ্যাশকোড রয়েছে। জেভিএম অভ্যন্তরীণভাবে হ্যাশটবেলটিকে আসল ঠিকানা সহ হ্যাশকোড সঞ্চয় করতে ব্যবহার করে এবং যখন প্রয়োজন হয় তখন আসল ঠিকানা পুনরুদ্ধার করতে একটি হ্যাশ অ্যালগরিদম ব্যবহার করে।
বিয়োগাস্তে

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

@ মাইনাসসভিন: আমি সম্মত। পয়েন্টার বাস্তবায়নের বিবরণ ভাষা / রানটাইমের উপর খুব বেশি নির্ভর করে। তবে আমি মনে করি যে বিশদগুলি নির্দিষ্ট প্রশ্নের জন্য প্রাসঙ্গিক নয়।
স্টিফান

4

দ্রুত উদাহরণ (নোটের পরিবর্তনশীল নামগুলি সংরক্ষণ করা হয় না):

void main()
{
  int X = 3;
  int *Y = X;
  int *Z = null;
} // void main(...)


...........................
....+-----+--------+.......
....|     |   X    |.......
....+-----+--------+.......
....| 100 |   3    |<---+..
....+-----+--------+....|..
........................|..
....+-----+--------+....|..
....|     |   Y    |....|..
....+-----+--------+....|..
....| 102 |  100   +----+..
....+-----+--------+.......
...........................
....+-----+--------+.......
....|     |   z    |.......
....+-----+--------+.......
....| 104 |   0    |.......
....+-----+--------+.......
...........................

চিয়ার্স।

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