সি ++ এ একটি পয়েন্টার মোছা হচ্ছে


92

প্রসঙ্গ: আমি পয়েন্টারের আশেপাশে আমার মাথা গুটিয়ে দেওয়ার চেষ্টা করছি, আমরা কয়েক সপ্তাহ আগে স্কুলে তাদের দেখেছি এবং আজ অনুশীলন করার সময় আমি নির্বোধে ছুটে এসেছি? ইস্যু, এটি আপনার কাছে সহজ সোজা হতে পারে তবে আমার কাছে প্রোগ্রামিংয়ের অভিজ্ঞতা কমই আছে।

পয়েন্টার মুছে ফেলার বিষয়ে আমি এসও-তে বেশ কয়েকটি প্রশ্ন দেখেছি তবে সেগুলি একটি ক্লাস মুছে ফেলার সাথে সম্পর্কিত বলে মনে হচ্ছে এবং একটি 'সরল' পয়েন্টার নয় (বা উপযুক্ত শব্দটি যাই হোক না কেন), আমি কোডটি চেষ্টা করছি চালান:

#include <iostream>;

using namespace std;

int main() {
  int myVar,
      *myPointer;

  myVar = 8;
  myPointer = &myVar;

  cout << "delete-ing pointers " << endl;
  cout << "Memory address: " << myPointer << endl;

  // Seems I can't *just* delete it, as it triggers an error 
  delete myPointer;
  cout << "myPointer: " << myPointer << endl;
  // Error: a.out(14399) malloc: *** error for object 0x7fff61e537f4:
  // pointer being freed was not allocated
  // *** set a breakpoint in malloc_error_break to debug
  // Abort trap: 6

  // Using the new keyword befor deleting it works, but
  // does it really frees up the space? 
  myPointer = new int;
  delete myPointer;
  cout << "myPointer: " << myPointer << endl;
  // myPointer continues to store a memory address.

  // Using NULL before deleting it, seems to work. 
  myPointer = NULL;
  delete myPointer;
  cout << "myPointer: " << myPointer << endl;
  // myPointer returns 0.

}

সুতরাং আমার প্রশ্নগুলি হ'ল:

  1. প্রথম মামলা কেন কাজ করবে না? কোনও পয়েন্টার ব্যবহার এবং মুছতে সর্বাধিক সরল ব্যবহার বলে মনে হচ্ছে? ত্রুটি বলে মেমরি বরাদ্দ দেওয়া হয়নি তবে 'কাউট' একটি ঠিকানা ফেরত দিয়েছে।
  2. দ্বিতীয় উদাহরণে ত্রুটিটি ট্রিগার করা হচ্ছে না তবে মাইপয়েন্টারটির মানটির একটি কাউট করা এখনও একটি স্মৃতি ঠিকানা ফেরায় ?
  3. # 3 কি সত্যিই কাজ করে? আমার কাছে কাজ করার মতো মনে হচ্ছে, পয়েন্টারটি আর কোনও ঠিকানা সঞ্চয় করছে না, এটি কি পয়েন্টার মোছার সঠিক উপায়?

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


16
আপনি প্রথম উদাহরণটি না দেখার কারণটি ভুল কারণ। শুধু deleteআপনি কি new। আপনি মুছে ফেলার পরেও পয়েন্টারটির নিজেকে নুল এ সেট করতে হবে না। আপনি যদি সেখানে সুরক্ষা চান তবে স্মার্ট পয়েন্টারগুলি ব্যবহার করুন যা আপনার জন্য স্মৃতিশক্তি মুক্ত করে এবং যখন তারা কিছু না রাখে তখন অ্যাক্সেস করার চেষ্টা করার সময় ত্রুটি দেয়।
খ্রিস্ট

হুঁ ঠিক আছে, আমি স্মার্ট পয়েন্টারগুলি কী তা নিশ্চিত নই, তবে আমি এটি সন্ধান করব, ধন্যবাদ!
লিওপিক

4
সংক্ষেপে, তারা আমার বর্ণনার মতো করে। নতুন কিছু রাখার জন্য, আপনি কল করুন resetএবং এটি পুরানোটিকে মুক্তি দেয়। প্রতিস্থাপন ছাড়াই এটি মুক্ত করতে, আপনি কল করুন release। যখন এটি সুযোগের বাইরে চলে যায়, এটি ধ্বংস হয়ে যায় এবং এটি কী ধরণের ভিত্তিতে মেমরিটি মুক্ত করতে পারে। std::unique_ptrশুধুমাত্র একটি মালিকের জন্য বোঝানো হয়। std::shared_ptrশেষ মালিক যখন সংস্থানটির মালিকানা বন্ধ করে দেয় তখন এটিকে মুক্ত করে। তারাও ব্যতিক্রম নিরাপদ। আপনি যদি একটি দিয়ে কোনও সংস্থান বরাদ্দ করেন, এবং তারপরে কোনও ব্যতিক্রমের মুখোমুখি হন, তবে উত্সটি সঠিকভাবে মুক্ত হবে be
ক্রিস

উত্তর:


168

1 এবং 2

myVar = 8; //not dynamically allocated. Can't call delete on it.
myPointer = new int; //dynamically allocated, can call delete on it.

প্রথম ভেরিয়েবলটি স্ট্যাকের জন্য বরাদ্দ করা হয়েছিল। newঅপারেটরটি ব্যবহার করে আপনি কেবল গতিযুক্তরূপে (গাদাতে) বরাদ্দ হওয়া মেমরির উপর আপনি মুছুন কল করতে পারেন ।

ঘ।

  myPointer = NULL;
  delete myPointer;

উপরোক্ত কিছু করেনি । আপনি কিছুই মুক্ত করেন নি, যেমনটি পয়েন্টারটি এনআরএল-তে নির্দেশ করেছে।


নিম্নলিখিতগুলি করা উচিত নয়:

myPointer = new int;
myPointer = NULL; //leaked memory, no pointer to above int
delete myPointer; //no point at all

ফাঁস মেমরিটিকে পিছনে রেখে (আপনি যে নতুন নতুন বরাদ্দ করেছেন) আপনি এটিকে নূলে লক্ষ্য করেছেন। আপনি যে স্মৃতিটি নির্দেশ করেছেন সেটিকে আপনার মুক্ত করা উচিত। বরাদ্দকৃত এই অ্যাক্সেসের কোনও উপায় new intনেই, সুতরাং মেমরি ফাঁস।


সঠিক উপায়:

myPointer = new int;
delete myPointer; //freed memory
myPointer = NULL; //pointed dangling ptr to NULL

আরও ভাল উপায়:

আপনি যদি সি ++ ব্যবহার করেন তবে কাঁচা পয়েন্টার ব্যবহার করবেন না । ব্যবহার করুন স্মার্ট পয়েন্টার পরিবর্তে যা সামান্য উপরি আপনার জন্য এই জিনিস সব ব্যবস্থা করতে সক্ষম। সি ++ 11 বেশ কয়েকটি নিয়ে আসে ।


13
<pedantry> "স্ট্যাকের উপরে" একটি বাস্তবায়ন বিশদ - যা সি ++ স্পষ্টভাবে উল্লেখ করা এড়ানো যায়। আরও সঠিক শব্দটি হ'ল "স্বয়ংক্রিয় স্টোরেজ সময়কাল সহ"। (সি ++ 11, 3.7.3) </
pedantry

4
ধন্যবাদ, আমি আপনার উত্তরটি ক এর জন্য নির্বাচন করেছি) কী ভুল ছিল তা ব্যাখ্যা করে এবং খ) সেরা অনুশীলন দেওয়া, অনেক অনেক ধন্যবাদ!
লিওপিক

6
পছন্দ করুন delete myPointerdeallocates *myPointer। ঐটা ঠিক. তবে myPointerএমন স্মৃতি অবস্থানের দিকে ইঙ্গিত করে যা মুক্ত হয়েছে এবং এটি ইউবি হিসাবে ব্যবহার করা উচিত নয়। স্কোপটি শেষ হওয়ার পরে এটি অ্যাক্সেসযোগ্য হবে কেবল যদি এটি প্রথম স্থানে স্থানীয় ভেরিয়েবল হয়।
অনিরুদ রমনাথন

4
ধন্যবাদ! (আমি আক্ষরিক) newপ্রতিদিন কিছু শিখি । (আমি
উদাসীন

4
@ আমলেসালিবাসিক স্ট্যাকের ভেরিয়েবলের সাথে যুক্ত স্মৃতিটি কেবল সুযোগের বাইরে চলে গেলেই মুক্ত করা হবে। NULLএটি পরবর্তীতে এর অপব্যবহার থেকে আমাদের রোধ করার জন্য এ্যাসাইন করা।
অনিরুধ রমনাথন

24

আমি বিশ্বাস করি আপনি কীভাবে পয়েন্টার কাজ করেন তা পুরোপুরি বুঝতে পারছেন না।
আপনি যখন কোনও মেমোরিটির দিকে কোনও পয়েন্টার দেখিয়ে থাকেন সেখানে তিনটি পৃথক জিনিস আপনাকে বুঝতে হবে:
- পয়েন্টারটির (মেমরি) দ্বারা "কী নির্দেশিত" রয়েছে
- এই মেমরি ঠিকানা
- সমস্ত পয়েন্টারগুলির স্মৃতি মুছে ফেলার দরকার নেই: আপনি কেবল ডায়নামিকভাবে বরাদ্দ করা মেমরি মুছে ফেলতে হবে (ব্যবহৃত newঅপারেটর)।

কল্পনা করুন:

int *ptr = new int; 
// ptr has the address of the memory.
// at this point, the actual memory doesn't have anything.
*ptr = 8;
// you're assigning the integer 8 into that memory.
delete ptr;
// you are only deleting the memory.
// at this point the pointer still has the same memory address (as you could
//   notice from your 2nd test) but what inside that memory is gone!

যখন আপনি করেছেন

ptr = NULL;
// you didn't delete the memory
// you're only saying that this pointer is now pointing to "nowhere".
// the memory that was pointed by this pointer is now lost.

সি ++ আপনাকে এমন deleteকোনও পয়েন্টারটিতে চেষ্টা করার অনুমতি দেয় যা নির্দেশ করে nullকিন্তু এটি আসলে কিছুই করে না, কেবল কোনও ত্রুটি দেয় না।


4
ধন্যবাদ, এটি অত্যন্ত সহায়ক ছিল, আমি ভেবেছিলাম আমার কাছে সমস্ত পয়েন্টার মুছতে হবে, জানতাম না যে কেবল নতুনদের জন্যই ছিল, ধন্যবাদ।
লিওপিক

13

পয়েন্টারগুলি সাধারণ ভেরিয়েবলগুলির সমান যা আপনার সেগুলি মুছতে হবে না। এগুলি ফাংশন সম্পাদন এবং / বা প্রোগ্রামের শেষে মেমরি থেকে সরানো হয়।

তবে আপনি মেমরির একটি 'ব্লক' বরাদ্দ করতে পয়েন্টার ব্যবহার করতে পারেন, উদাহরণস্বরূপ:

int *some_integers = new int[20000]

এটি 20000 পূর্ণসংখ্যার জন্য মেমরির স্থান বরাদ্দ করবে। দরকারী, কারণ স্ট্যাকের একটি সীমিত আকার রয়েছে এবং আপনি স্ট্যাকের ওভারফ্লো ত্রুটি ছাড়াই একটি বড় আকারের 'ints' নিয়ে গণ্ডগোল করতে চাইতে পারেন।

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

delete [] some_integers;

আশা করি এইটি কাজ করবে.


4
আমি কেবল যুক্ত করতে চাই যে বরাদ্দ হওয়া মেমরিটি অন্যান্য প্রোগ্রামগুলি ব্যবহারের জন্য ফিরে আসবে তবে কেবলমাত্র আপনার প্রোগ্রামের সম্পাদন শেষ হয়েছে।
sk4l

7

সি ++ তে একটি নিয়ম রয়েছে, প্রতিটি নতুনের জন্য একটি মুছে ফেলা হয়

  1. প্রথম মামলা কেন কাজ করবে না? কোনও পয়েন্টার ব্যবহার এবং মুছতে সর্বাধিক সরল ব্যবহার বলে মনে হচ্ছে? ত্রুটি বলে মেমরি বরাদ্দ দেওয়া হয়নি তবে 'কাউট' একটি ঠিকানা ফেরত দিয়েছে।

নতুন বলা হয় না। সুতরাং যে ঠিকানাটি কাউট প্রিন্ট করে তা হ'ল মাইভারের মেমরির অবস্থানের ঠিকানা, বা এই ক্ষেত্রে মাইপয়েন্টারে নির্ধারিত মান। লিখিত ভাবে:

myPointer = &myVar;

তুমি বলো:

মাইপয়েন্টার = মাইভারে ডেটা কোথায় সংরক্ষণ করা হয়েছে তার ঠিকানা

  1. দ্বিতীয় উদাহরণে ত্রুটিটি ট্রিগার করা হচ্ছে না তবে মাইপয়েন্টারটির মানটি কি এখনও একটি স্মৃতি ঠিকানা ফেরায়?

এটি এমন ঠিকানা প্রদান করে যা মুছে ফেলা একটি স্মৃতি অবস্থানের দিকে নির্দেশ করে। কারণ প্রথমে আপনি পয়েন্টারটি তৈরি করেন এবং এর মানটি আমার পয়েন্টারে অর্পণ করেন, দ্বিতীয়টি আপনি এটি মুছুন, তৃতীয় আপনি এটি মুদ্রণ করুন। সুতরাং আপনি যদি আমার পয়েন্টারে অন্য কোনও মান নির্ধারণ না করেন তবে মুছে ফেলা ঠিকানাটি রয়ে যাবে।

  1. # 3 কি সত্যিই কাজ করে? আমার কাছে কাজ করার মতো মনে হচ্ছে, পয়েন্টারটি আর কোনও ঠিকানা সঞ্চয় করছে না, এটি কি পয়েন্টার মোছার সঠিক উপায়?

নুল 0 টি সমান, আপনি 0 মুছুন, তাই আপনি কিছুই মুছবেন না। এবং এটি যুক্তিযুক্ত যে এটি 0 টি মুদ্রণ করে কারণ আপনি করেছেন:

myPointer = NULL;

যা সমান:

myPointer = 0;

4
  1. আপনি স্ট্যাকের উপর বরাদ্দকৃত একটি ভেরিয়েবল মোছার চেষ্টা করছেন। আপনি এটা করতে পারেন না
  2. একটি পয়েন্টার মোছা আসলে কোনও পয়েন্টারকে ধ্বংস করে না, কেবল দখল করা মেমরিটি ওএসকে ফেরত দেওয়া হয়। আপনি এটিকে অ্যাক্সেস করতে পারবেন ততক্ষণ মেমরিটি অন্য ভেরিয়েবলের জন্য ব্যবহার করা হয়, বা অন্যথায় ম্যানিপুলেটেড হয়। সুতরাং মোছার পরে NULL (0) এ একটি পয়েন্টার সেট করা ভাল অনুশীলন।
  3. একটি নল পয়েন্টার মোছা কিছু মুছবে না।

2
int value, *ptr;

value = 8;
ptr = &value;
// ptr points to value, which lives on a stack frame.
// you are not responsible for managing its lifetime.

ptr = new int;
delete ptr;
// yes this is the normal way to manage the lifetime of
// dynamically allocated memory, you new'ed it, you delete it.

ptr = nullptr;
delete ptr;
// this is illogical, essentially you are saying delete nothing.

4
এছাড়াও, স্ট্যাক ফ্রেমে youtube.com/watch?v=bjObm0hxIYY , এবং ইউটিউব .com/ watch ?v =Rxvv9krECNw পয়েন্টারগুলিতে এই বক্তৃতাটি দেখুন ।
ক্যাস্পার বিয়ার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.