বিনামূল্যে পরে NULL এ পরিবর্তনশীল সেট করা হচ্ছে


156

আমার সংস্থায় একটি কোডিং বিধি রয়েছে যা বলে যে কোনও স্মৃতি মুক্ত করার পরে ভেরিয়েবলটি পুনরায় সেট করুন NULL। উদাহরণ স্বরূপ ...

void some_func () 
{
    int *nPtr;

    nPtr = malloc (100);

    free (nPtr);
    nPtr = NULL;

    return;
}

আমি অনুভব করি যে, উপরে প্রদর্শিত কোডের মতো ক্ষেত্রেও সেট করার NULLকোনও অর্থ হয় না। নাকি আমি কিছু মিস করছি?

এই জাতীয় ক্ষেত্রে যদি কোনও অর্থ না থাকে তবে আমি এই কোডিং নিয়মটি সরিয়ে নিতে "মানের দল" এর সাথে এটি নিয়ে যাচ্ছি। আপনার পরামর্শ দিন.


2
এটির ptr == NULLসাথে কিছু করার আগে চেক করতে সক্ষম হওয়া সর্বদা দরকারী । আপনি যদি আপনার ফ্রি পয়েন্টারগুলি বাতিল করতে না পারেন ptr != NULLতবে এখনও অব্যর্থ পয়েন্টার।
কি জে

ঝুঁকিপূর্ণ পয়েন্টারগুলি ব্যবহার-পরে- মুক্তের মতো শোষণযোগ্য দুর্বলতার দিকে নিয়ে যেতে পারে।
Ван

উত্তর:


285

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

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

শৈলীটি সম্পূর্ণ করতে, আপনাকে একটি সত্য পয়েন্টার মান নির্ধারণের আগে পয়েন্টারগুলি NUL এ সূচনা করতে হবে।


3
আমি বুঝতে পারছি না কেন আপনি "সত্যিকারের পয়েন্টার মান নির্ধারিত হওয়ার আগেই তারা" NULL এর দিকে সূচনা করবেন "?
পল বিগগার 14

26
@ পল: নির্দিষ্ট ক্ষেত্রে, ঘোষণাটি পড়তে পারে int *nPtr=NULL;। এখন, আমি সম্মত হব যে এটি পরের লাইনে ডানদিকে অনুসরণ করে একটি অতিরিক্ত কাজ করবে red যাইহোক, যদি ঘোষণা এবং প্রথম আরম্ভের মধ্যে কোড থাকে তবে কারও কারও এখনও ভেরিয়েবল ব্যবহার শুরু হতে পারে যদিও এর কোনও মূল্য নেই has আপনি যদি নাল-ইনিশিয়ালাইজ করেন তবে আপনি সেগফল্ট পাবেন; ছাড়া, আপনি আবার এলোমেলো মেমরি পড়তে বা লিখতে পারেন। তেমনিভাবে, পরে যদি ভেরিয়েবলটি কেবল শর্তসাপেক্ষে আরম্ভ হয় তবে পরে ত্রুটিযুক্ত অ্যাক্সেসগুলি আপনাকে তাত্ক্ষণিক ক্র্যাশ দেওয়া উচিত যদি আপনি শূন্য-আরম্ভ করার কথা মনে রাখেন।
মার্টিন বনাম লুইস

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

9
উইলহেল্ম, পয়েন্টটি হ'ল নাল পয়েন্টার ডিरेফারেন্সের সাহায্যে আপনি ক্র্যাশ এবং সমস্যার আসল অবস্থান নির্ধারণ করুন। একটি খারাপ অ্যাক্সেস ক্র্যাশ হতে পারে এবং নাও পারে এবং অপ্রত্যাশিত জায়গায় অপ্রত্যাশিত উপায়ে ডেটা বা আচরণকে দূষিত করে।
অমিত নাইডু

4
প্রকৃতপক্ষে, এনयुএলএলকে পয়েন্টার শুরু করার ক্ষেত্রে কমপক্ষে একটি উল্লেখযোগ্য ত্রুটি রয়েছে: এটি সংকলকটিকে আপনাকে অনির্দেশে পরিবর্তনশীল সম্পর্কে সতর্ক করতে বাধা দিতে পারে। যদি না আপনার কোডটির যুক্তি প্রকৃতপক্ষে পয়েন্টারের (যেমন যদি (এনপিআরটি == ন্যুআলএল) ডোজোমিং ... ...) এর জন্য সেই মানটি পরিচালনা করে না তবে এটিকে যেমন রয়েছে তেমন রেখে দেওয়া ভাল।
এরিক

37

NULLপরে একটি পয়েন্টার সেট freeকরা একটি সন্দেহজনক অনুশীলন যা প্রায়শই স্বতঃস্ফূর্তভাবে মিথ্যা ভিত্তিতে "ভাল প্রোগ্রামিং" বিধি হিসাবে জনপ্রিয় হয়। এটি এমন "ভুয়া সত্য" বিভাগগুলির মধ্যে একটি যা "সঠিক বলে মনে হয়" বিভাগের সাথে সম্পর্কিত তবে বাস্তবে বাস্তবে কার্যকর কোনও কিছুই অর্জন করে না (এবং কখনও কখনও নেতিবাচক পরিণতির দিকে পরিচালিত করে)।

কথিতভাবে, একই পয়েন্টারটির মান একাধিকবার পাস করার NULLপরে freeভয়ঙ্কর "ডাবল ফ্রি" সমস্যাটি প্রতিরোধ করার কথা পরে পয়েন্টার সেট করা free। বাস্তবে যদিও, 10 টির মধ্যে 9 ক্ষেত্রে সত্য "ডাবল ফ্রি" সমস্যা দেখা দেয় যখন একই পয়েন্টার মান ধারণকারী বিভিন্ন পয়েন্টার অবজেক্টগুলি আর্গুমেন্ট হিসাবে ব্যবহৃত হয় free। বলা বাহুল্য, এই জাতীয় সমস্যা প্রতিরোধের জন্য একেবারে কিছুই অর্জনের NULLপরে একটি পয়েন্টার সেট করা free

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

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


1
স্পষ্টভাবে. আমি কখনও কখনও দ্বৈত-মুক্তির কারণ মনে করি না যা বিনামূল্যে দেওয়ার পরে নুলকে পয়েন্টার সেট করে স্থির করা হত, তবে আমি প্রচুর পরিমাণে করেছি যা তা নয়।
LnxPrgr3

4
@ অ্যান্ট "সন্দেহজনক" কিছুটা বেশি। এটি সব ব্যবহারের ক্ষেত্রে নির্ভর করে। যদি পয়েন্টারের মানটি কখনও সত্য / মিথ্যা অর্থে ব্যবহৃত হয় তবে এটি কেবল একটি বৈধ অনুশীলনই নয়, এটি একটি সেরা অনুশীলন।
কোডার

1
@ কোডার সম্পূর্ণ ভুল। কলটি মুক্ত করার আগে কোনও বস্তুর দিকে ইঙ্গিত করেছে কিনা তা যদি জানতে পয়েন্টারটির মানটি সত্য মিথ্যা অর্থে ব্যবহার করা হয়, তবে এটি কেবল সেরা অনুশীলনই নয়, এটিও ভুল । উদাহরণস্বরূপ: foo* bar=getFoo(); /*more_code*/ free(bar); /*more_code*/ return bar != NULL;। এখানে, কল barকরার NULLপরে সেটিংস স্থাপনের freeফলে ফাংশনটি মনে করে যে এটির কোনও বার ছিল না এবং ভুল মানটি ফিরে আসবে!
ডেভিড শোয়ার্জ

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

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

34

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

উভয় কারণে, ফ্রি () এর পরে পয়েন্টারটি NULL এ সেট করা ভাল ধারণা হতে পারে। যদিও এটি সর্বদা প্রয়োজন হয় না। উদাহরণস্বরূপ, যদি পয়েন্টার ভেরিয়েবলটি ফ্রি () এর পরে অবিলম্বে সুযোগের বাইরে চলে যায় তবে এটিকে নূলে সেট করার খুব বেশি কারণ নেই।


1
+1 এটি আসলে খুব ভাল পয়েন্ট। "ডাবল ফ্রি" (যা সম্পূর্ণ বোগাস) সম্পর্কে যুক্তি নয়, তবে এটি । আমি পরে পয়েন্টারগুলির যান্ত্রিক নুল-ইনিংয়ের অনুরাগী নই free, তবে এটি প্রকৃত অর্থে উপলব্ধি করে।
এ্যান্ট

যদি আপনি একই পয়েন্টারের মাধ্যমে মুক্ত করার পরে কোনও পয়েন্টার অ্যাক্সেস করতে পারেন তবে এটি আরও বেশি সম্ভাবনা রয়েছে যে আপনি অন্য কোনও পয়েন্টারের মাধ্যমে যে বিষয়টিকে নির্দেশ করেছেন সেটিকে মুক্ত করার পরে আপনি কোনও পয়েন্টার অ্যাক্সেস করতে পারবেন। সুতরাং এটি আপনাকে মোটেও সহায়তা করে না - আপনাকে এখনও অন্য পয়েন্টারের মাধ্যমে কোনও পয়েন্টারের মাধ্যমে মুক্ত করার পরে কোনও পয়েন্টারের মাধ্যমে কোনও অ্যাক্সেস অ্যাক্সেস না করা নিশ্চিত করার জন্য আপনাকে অন্য কিছু প্রক্রিয়া ব্যবহার করতে হবে। একই পয়েন্টার ক্ষেত্রেও রক্ষা করতে আপনি সেই পদ্ধতিটি ব্যবহার করতে পারেন।
ডেভিড শোয়ার্জ

1
@ ডেভিডশওয়ার্টজ: আমি আপনার মন্তব্যের সাথে একমত নই। কয়েক সপ্তাহ আগে যখন আমাকে একটি বিশ্ববিদ্যালয় অনুশীলনের জন্য একটি স্ট্যাক লিখতে হয়েছিল তখন আমার সমস্যা হয়েছিল, আমি কয়েক ঘন্টা তদন্ত করেছিলাম। আমি ইতিমধ্যে কিছু ফ্রি মেমরি অ্যাক্সেস করেছি কিছু সময়ে (ফ্রিটি কিছু প্রথম দিকে লাইন ছিল)। এবং কখনও কখনও এটি খুব অদ্ভুত আচরণের দিকে পরিচালিত করে। যদি আমি মুক্ত করার পরে পয়েন্টারটি এনইউএলএল করে দিতাম তবে সেখানে একটি "সরল" সেগফল্ট থাকত এবং আমি কয়েক ঘন্টা কাজ বাঁচাতে পারতাম। সুতরাং এই উত্তর জন্য +1!
মোজবোজ

2
@ কেটজে_সন এমনকি একটি থামানো ঘড়িও দিনে দু'বার ঠিক is এটি অনেক বেশি সম্ভাবনা রয়েছে যে এনএলএল-এর দিকে নির্দেশকগুলি সেট করা এনআরএল-এর জন্য পরীক্ষা করে কোডটিতে সেগফল্টিং থেকে ইতিমধ্যে মুক্তিপ্রাপ্ত বস্তুগুলিকে ভ্রান্ত প্রবেশাধিকার রোধ করে ত্রুটিগুলি আড়াল করবে এবং তারপরে চেক করা উচিত এমন কোনও বিষয় যাচাই করতে নীরবে ব্যর্থ হয়। (সম্ভবত সুনির্দিষ্ট ডিবাগ বিল্ডগুলিতে বিনামূল্যে এন.এল.এল.-এর নির্দেশক স্থাপন কার্যকর হতে পারে, বা সেগফল্টের গ্যারান্টিযুক্ত NULL ব্যতীত অন্য কোনও মূল্যে সেট করা অর্থবোধক হতে পারে But তবে এই বুদ্ধিটি আপনাকে একবার সাহায্য করার জন্য ঘটেছে তার পক্ষে পক্ষে যুক্তি নয়) ।)
ডেভিড শোয়ার্জ

@ ডেভিডশওয়ার্টজ ওয়েল, এটি যুক্তিসঙ্গত মনে হচ্ছে ... আপনার মন্তব্যের জন্য ধন্যবাদ, আমি ভবিষ্যতে এটি বিবেচনা করব! :) +1
মোজবোজজ

20

ওভাররাইট মেমরি এড়াতে এটি ভাল অনুশীলন হিসাবে বিবেচিত হয়। উপরের ফাংশনে, এটি অপ্রয়োজনীয়, তবে প্রায়শই এটি করা হয়ে গেলে অ্যাপ্লিকেশন ত্রুটি খুঁজে পেতে পারে।

পরিবর্তে এই জাতীয় কিছু চেষ্টা করুন:

#if DEBUG_VERSION
void myfree(void **ptr)
{
    free(*ptr);
    *ptr = NULL;
}
#else
#define myfree(p) do { void ** __p = (p); free(*(__p)); *(__p) = NULL; } while (0)
#endif

DEBUG_VERSION আপনাকে প্রোফাইল ডিবাগিং কোডে মুক্ত করতে দেয়, তবে উভয়ই কার্যত একই।

সম্পাদনা : যোগ করুন ... নীচের পরামর্শ মতো, ধন্যবাদ Added


3
যদি আপনি বন্ধনী ছাড়াই যদি একটি বিবৃতি পরে ব্যবহার করেন তবে ম্যাক্রো সংস্করণটিতে একটি সূক্ষ্ম বাগ রয়েছে।
মার্ক রান্সম

(শূন্য) 0 এর সাথে কী? এই কোডটি করুন: যদি (এক্স) মাইফ্রি (& এক্স); অন্যথায় do_foo (); (x) {ফ্রি (* (& এক্স)) হয়ে যায়; * (& x) = নাল; } শূন্য 0; অন্যথায় do_foo (); অন্যটি একটি ত্রুটি।
jmucchiello

সেই ম্যাক্রোটি কমা অপারেটরের জন্য উপযুক্ত জায়গা: ফ্রি ( (পি)), * (পি) = নাল। অবশ্যই পরবর্তী সমস্যাটি এটি * (পি) দুবার মূল্যায়ন করে। এটি {অকার্যকর * _ পিপি = (পি) হওয়া উচিত; ফ্রি p & P); * _ পিপি = নাল; Prep প্রিপ্রোসেসর মজা নয়।
jmucchiello

5
ম্যাক্রোটি খালি বন্ধনীতে থাকা উচিত নয়, এটি কোনও do { } while(0)ব্লকের মধ্যে থাকা উচিত যাতে এটি if(x) myfree(x); else dostuff();ভেঙে না যায়।
ক্রিস লুটজ

3
লুৎজ যেমন বলেছিল, ম্যাক্রো বডি do {X} while (0)হ'ল ম্যাক্রো বডি তৈরির সর্বোত্তম উপায় যা একটি ফাংশন "পছন্দ করে এবং এর মতো কাজ করে"। বেশিরভাগ সংকলকরা যাইহোক লুপটি অপ্টিমাইজ করে।
মাইক ক্লার্ক

7

আপনি যদি বিন্দুতে মুক্ত হয়ে () d হয়ে পৌঁছে থাকেন তবে তা ভেঙে যেতে পারে বা নাও হতে পারে। সেই স্মৃতিটি আপনার প্রোগ্রামের অন্য অংশে পুনরায় স্থানান্তরিত হতে পারে এবং তারপরে আপনি মেমরির দুর্নীতি পান,

আপনি যদি পয়েন্টারটিকে NULL এ সেট করেন, তবে আপনি যদি এটি অ্যাক্সেস করেন তবে প্রোগ্রামটি সর্বদা একটি সেগফোল্ট দিয়ে ক্র্যাশ হয়। আর নেই, কখনও কখনও এটি '', আর কোনও কাজ করে না ', অবিশ্বাস্য উপায়ে ক্র্যাশ হয়।' এটি ডিবাগ করা সহজ উপায়।


5
প্রোগ্রামটি সবসময় একটি সেগফল্ট দিয়ে ক্রাশ হয় না। আপনি পয়েন্টারে অ্যাক্সেস করার উপায়টির অর্থ যদি এই হয় যে ডিসিফেরেন্সের আগে এটির জন্য যথেষ্ট পরিমাণে অফসেট প্রয়োগ করা হয় তবে এটি ঠিকঠাক মেমোরিতে পৌঁছতে পারে: ((মাইহিউজস্ট্রাক্ট *) 0) -> ফিল্ড নয়ারডেন্ড। এবং এটি এমন কোনও হার্ডওয়্যার মোকাবেলা করার আগেও যা 0 টি অ্যাক্সেসে মোটেও সেগফল্ট করে না। তবে প্রোগ্রামটি সেগফল্ট দিয়ে ক্রাশ হওয়ার সম্ভাবনা বেশি to
স্টিভ জেসোপ

7

পয়েন্টারটিকে free'ডি মেমোরিতে সেট করার অর্থ পয়েন্টারের মাধ্যমে সেই মেমরিটিতে অ্যাক্সেসের যে কোনও প্রচেষ্টা অবিলম্বে ক্রাশ হয়ে যাবে, পরিবর্তিত আচরণের পরিবর্তে। জিনিসগুলি কোথায় ভুল হয়েছে তা নির্ধারণ করা এটি আরও সহজ করে তোলে।

আমি আপনার তর্কটি দেখতে পাচ্ছি: যেহেতু nPtrঠিক পরে সুযোগের বাইরে চলে যাচ্ছে nPtr = NULL, এটি সেট করার কোনও কারণ বলে মনে হচ্ছে না NULL। তবে কোনও structসদস্যের ক্ষেত্রে বা অন্য কোথাও যেখানে পয়েন্টারটি অবিলম্বে সুযোগের বাইরে চলে যাচ্ছে না, এটি আরও বেশি অর্থবোধ করে। সেই পয়েন্টারটি কোড দ্বারা আবার ব্যবহার করা হবে যা এটি ব্যবহার করা উচিত নয় তা অবিলম্বে স্পষ্ট নয়।

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


7

গ মধ্যে সর্বাধিক সাধারণ বাগটি ডাবল মুক্ত। মূলত আপনি এরকম কিছু করেন

free(foobar);
/* lot of code */
free(foobar);

এবং এটি শেষ পর্যন্ত খুব খারাপ, ওএস ইতিমধ্যে কিছু মুক্ত মেমরি মুক্ত করার চেষ্টা করে এবং সাধারণত এটি সেগফল্ট করে। সুতরাং ভাল অনুশীলনটি সেট করা হয় NULL, যাতে আপনি পরীক্ষা করতে পারেন এবং সত্যিকার অর্থে এই মেমরিটি মুক্ত করতে হবে কিনা তা পরীক্ষা করতে পারেন

if(foobar != null){
  free(foobar);
}

এছাড়াও লক্ষণীয় যে free(NULL)আপনি কিছু করতে পারবেন না যাতে আপনাকে বিবৃতি লিখতে হবে না। আমি আসলে কোনও ওএস গুরু নই তবে আমি বেশ সুন্দর এমনকি এখন বেশিরভাগ ওএস ডাবল ফ্রিতে ক্রাশ হবে।

আবর্জনা সংগ্রহের সমস্ত ভাষা (জাভা, ডটনেট) এ সমস্যা না হওয়ার এবং সামগ্রিকভাবে মেমরি পরিচালনা বিকাশকারীদের ছাড়তে না পেরে এই কারণেই এটি একটি প্রধান কারণও reason


11
আপনি চেক না করেই কেবল ফ্রি () কল করতে পারেন - ফ্রি (এনইউএল) কিছুই না করে সংজ্ঞায়িত করা হয়েছে।
আম্বার

5
কি বাগগুলি লুকায় না? (অনেকটা
নিখরচায় রাখার

1
থ্যাঙ্কস, আমি পেয়েছি আমি চেষ্টা করেছি:p = (char *)malloc(.....); free(p); if(p!=null) //p!=null is true, p is not null although freed { free(p); //Note: checking doesnot prevent error here }
শাবো ওয়াং

5
আমি যেমন বলেছি, যে পয়েন্টারের পাস হয়েছে তার মান পরিবর্তন free(void *ptr) করতে পারে না । এটি পয়েন্টারের বিষয়বস্তু , সেই ঠিকানায় সঞ্চিত ডেটা পরিবর্তন করতে পারে তবে ঠিকানাটি নিজেই বা পয়েন্টারের মান নয় । এর জন্য free(void **ptr)(যা স্ট্যান্ডার্ড দ্বারা দৃশ্যত অনুমোদিত নয়) বা ম্যাক্রো (যা অনুমোদিত এবং পুরোপুরি বহনযোগ্য তবে লোকে ম্যাক্রোগুলি পছন্দ করে না) প্রয়োজন হবে। এছাড়াও, সি সুবিধার্থে নয়, এটি প্রোগ্রামারদের যতটা চান নিয়ন্ত্রণ দেওয়ার বিষয়ে। যদি তারা পয়েন্টার সেট করার অতিরিক্ত ওভারহেড না চায় তবে NULLএটি তাদের উপর চাপিয়ে দেওয়া উচিত নয়।
ক্রিস লুটজ

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

6

এর পিছনে ধারণাটি হ'ল মুক্তি পয়েন্টারের দুর্ঘটনাক্রমে পুনরায় ব্যবহার বন্ধ করা।


4

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

আপনি যদি পয়েন্টারটি বাতিল করেন, তবে এটি ব্যবহারের যে কোনও প্রচেষ্টা 0x0 অবলম্বন করবে এবং ঠিক সেখানে ক্রাশ হবে, যা ডিবাগ করা সহজ। র্যান্ডম পয়েন্টারগুলি এলোমেলো মেমোরিটির দিকে নির্দেশ করে ডিবাগ করা শক্ত। এটি অবশ্যই প্রয়োজনীয় নয় তবে তারপরে এটি সর্বোত্তম অনুশীলনের নথিতে।


উইন্ডোজে, কমপক্ষে, ডিবাগ বিল্ডগুলি মেমরিটিকে 0xdddddddd তে সেট করে দেয় তাই আপনি যখন ডিলিট করা মেমরির জন্য পয়েন্টার ব্যবহার করবেন তখনই আপনি জানবেন। সমস্ত প্ল্যাটফর্মগুলিতে একই ব্যবস্থা থাকা উচিত।
i_am_jorf

2
জেফামফোন, মুছে ফেলা মেমরি ব্লকটি আপনি পুনরায় পয়েন্টারটি ব্যবহার করার পরে পুনরায় স্থান নির্ধারণ এবং অন্য কোনও অবজেক্টকে অর্পণ করতে পারে।
কনস্টান্টিন

4

এএনএসআই সি স্ট্যান্ডার্ড থেকে:

void free(void *ptr);

ফ্রি ফাংশন পিটিআর দ্বারা নির্দেশিত স্থানটির অবনতি ঘটায় যার অর্থ আরও বরাদ্দের জন্য উপলব্ধ করা হয়। যদি পিটিআরটি নাল পয়েন্টার হয় তবে কোনও ক্রিয়া ঘটে না। অন্যথায়, যদি আর্গুমেন্টটি কলোক, ম্যালোক বা রিলোক ফাংশন দ্বারা পূর্বে ফিরে আসা কোনও পয়েন্টারের সাথে মেলে না, বা যদি স্থানটি মুক্ত বা রিলোকের কল দ্বারা বিলোপ করা হয়েছে, আচরণটি সংজ্ঞায়িত।

"অপরিজ্ঞাত আচরণ" প্রায়শই একটি প্রোগ্রাম ক্রাশ। এটি এড়াতে যাতে পয়েন্টারটি NUL এ রিসেট করা নিরাপদ। মুক্ত () নিজেই এটি করতে পারে না কারণ এটি কেবলমাত্র একটি পয়েন্টার দিয়ে যায়, কোনও পয়েন্টারের কাছে কোনও পয়েন্টার হয় না। আপনি নিখরচায় () এর একটি নিরাপদ সংস্করণও লিখতে পারেন যা পয়েন্টারটি শুভ করে:

void safe_free(void** ptr)
{
  free(*ptr);
  *ptr = NULL;
}

@ ড্রিপজা - একটি ত্রুটি (আমার মতে) এমন একটি বিষয় যা আপনার প্রোগ্রামটিকে যেমন অনুমান করা উচিত তেমন কাজ না করে। যদি কোনও লুকানো ডাবল ফ্রি আপনার প্রোগ্রামটি ভেঙে দেয় তবে এটি একটি ত্রুটি। যদি এটি ঠিক কীভাবে কাজ করে তা কাজ করে তবে এটি ত্রুটি নয়।
ক্রিস লুটজ

@ ড্রিপিজা: আমি কেবল একটি যুক্তি খুঁজে পেয়েছি যে মুখোশের NULLত্রুটিগুলি এড়াতে কেন এটির সেট করা উচিত । stackoverflow.com/questions/1025589/… মনে হয় উভয় ক্ষেত্রেই কিছু ত্রুটি লুকানো আছে।
জর্জি স্কলি

1
সচেতন থাকুন যে একটি শূন্য
সুরক্ষিত করুন

3
@ ক্রিস, না, সর্বোত্তম পন্থা হ'ল কোড কাঠামো। এলোমেলো মলোকগুলি আপনার সমস্ত কোডবেসে ফেলে দেবেন না, সম্পর্কিত জিনিসগুলি একসাথে রাখুন। "মডিউল" যা কোনও উত্স বরাদ্দ করে (মেমোরি, ফাইল, ...) এটি মুক্ত করার জন্য দায়ী এবং এটি করার জন্য একটি ফাংশন সরবরাহ করতে হয় যা পয়েন্টারগুলিকেও যত্ন করে রাখে। যে কোনও নির্দিষ্ট সংস্থার জন্য, আপনার ঠিক তখন একই জায়গা যেখানে এটি বরাদ্দ করা হয়েছে এবং যেখানে এটি প্রকাশ করা হয়েছে সেখানে একই জায়গা রয়েছে both
নিরাপদ

4
@ ক্রিস লুটজ: হোগওয়াশ। যদি আপনি একই পয়েন্টারটি দুবার মুক্ত করে এমন কোড লিখে থাকেন তবে আপনার প্রোগ্রামটিতে এটি একটি যৌক্তিক ত্রুটি রয়েছে। যৌক্তিক ত্রুটিটিকে ক্র্যাশ না করে মাস্কিংয়ের অর্থ এই নয় যে প্রোগ্রামটি সঠিক: এটি এখনও অযৌক্তিক কিছু করছে। এমন কোনও দৃশ্য নেই যেখানে ডাবল ফ্রি লেখার বিষয়টি ন্যায়সঙ্গত।
ড্রিপজা

4

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

যাইহোক - পয়েন্টারটি আবার ব্যবহার করার কথা না বললে আমি ভেরিয়েবলটি নালায় সেট করব না, তবে প্রায়শই উচ্চ স্তরের নকশা আমাকে যাইহোক এটি নালায় সেট করার কারণ দেয়। উদাহরণস্বরূপ, যদি পয়েন্টারটি কোনও শ্রেণীর সদস্য হয় এবং আমি এটি মুছে ফেলেছি তবে এটি "চুক্তি "টি নির্দেশ করে যা যদি আপনি শ্রেণীর পছন্দ করেন তবে সেই সদস্যটি যে কোনও সময় বৈধ কিছুতে নির্দেশ করবে তাই এটি অবশ্যই বাতিল করতে হবে এই কারণে. একটি ছোট পার্থক্য কিন্তু আমি মনে করি একটি গুরুত্বপূর্ণ এক।

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

একটি সাধারণ প্যাটার্ন হ'ল কন্সট্রাক্টরের সমস্ত সদস্য পয়েন্টারকে NUL এ সেট করে এবং ডেটাস্ট্রাক্টর কলটি মুছুন এমন কোনও পয়েন্টারে ডেটা যাতে আপনার নকশায় বলা হয় যে শ্রেণীর মালিকানা রয়েছে । স্পষ্টতই এই ক্ষেত্রে আপনাকে কোনও তথ্য মুছে ফেলার সময় আপনাকে কোনও তথ্য মুছে ফেলার সময় পয়েন্টারটি NULL এ সেট করতে হবে that

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


4

আমি উত্তরটি সন্ধান করার পরে আমি একই প্রশ্নটি দেখতে পেয়েছি। আমি এই সিদ্ধান্তে পৌঁছেছি:

এটি সর্বোত্তম অনুশীলন, এবং এটি সমস্ত (এম্বেডড) সিস্টেমে পোর্টেবল করার জন্য এটি অনুসরণ করতে হবে।

free()এটি একটি লাইব্রেরি ফাংশন, যা প্ল্যাটফর্মের পরিবর্তনের পরিবর্তে পরিবর্তিত হয়, সুতরাং আপনারা এই প্রত্যাশা করবেন না যে এই ফাংশনে পয়েন্টারটি পাস করার পরে এবং মেমরি মুক্ত করার পরে, এই পয়েন্টারটি ন্যূনল সেট করা হবে। প্ল্যাটফর্মের জন্য প্রয়োগ করা কিছু লাইব্রেরির ক্ষেত্রে এটি নাও হতে পারে।

সুতরাং সর্বদা জন্য যান

free(ptr);
ptr = NULL;

3

আপনি নিম্নলিখিত পরিস্থিতি এড়াতে চেষ্টা করার সময় এই নিয়মটি কার্যকর:

1) জটিল যুক্তি এবং মেমরি পরিচালনার সাথে আপনার একটি দীর্ঘ দীর্ঘ ফাংশন রয়েছে এবং আপনি ক্রিয়াকলাপে ঘটনাক্রমে মুছে ফেলা স্মৃতিতে পয়েন্টারটিকে পুনরায় ব্যবহার করতে চান না।

2) পয়েন্টারটি এমন একটি শ্রেণীর সদস্য পরিবর্তনশীল যার সাথে মোটামুটি জটিল আচরণ রয়েছে এবং আপনি অন্য ক্রিয়াকলাপগুলিতে মুছে ফেলা মেমরিটিতে ঘটনাক্রমে পয়েন্টারটিকে পুনরায় ব্যবহার করতে চান না।

আপনার দৃশ্যে, এটি পুরোপুরি অর্থবহ করে না, তবে যদি ফাংশনটি আরও দীর্ঘতর হয় তবে তা বিবেচনাধীন হতে পারে।

আপনি যুক্তি দিতে পারেন যে এটি NUL এ সেট করা আসলে লজিক ত্রুটিগুলি পরবর্তীতে মাস্ক করতে পারে বা আপনি যে ক্ষেত্রে এটি বৈধ বলে ধরেছেন সেখানে আপনি এখনও ন্যূনএলকে ক্র্যাশ করেছেন, সুতরাং এটি কোনও বিষয় নয়।

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


2

অন্যরা যা বলেছে তাতে যুক্ত করতে পয়েন্টার ব্যবহারের একটি ভাল পদ্ধতি হ'ল এটি বৈধ পয়েন্টার কিনা তা সর্বদা পরীক্ষা করা। কিছুটা এইরকম:


if(ptr)
   ptr->CallSomeMethod();

সুস্পষ্টভাবে পয়েন্টারটিকে NULL হিসাবে চিহ্নিত করার পরে এটি সি / সি ++ এ এই জাতীয় ব্যবহারের অনুমতি দেয়।


5
অনেক ক্ষেত্রে, যেখানে কোনও NULL পয়েন্টারটি বোঝায় না, পরিবর্তে একটি দৃser়তা লিখাই ভাল।
এরিচ কিটজমুয়েলার

2

এটি NULL- র সমস্ত পয়েন্টারকে সূচনা করার পক্ষে আরও একটি যুক্তি হতে পারে তবে এর মতো কিছু খুব স্নিগ্ধ বাগ হতে পারে:

void other_func() {
  int *p; // forgot to initialize
  // some unrelated mallocs and stuff
  // ...
  if (p) {
    *p = 1; // hm...
  }
}

void caller() {
  some_func();
  other_func();
}

pপূর্ববর্তী হিসাবে স্ট্যাকের একই জায়গায় শেষ হয় nPtr, সুতরাং এটি এখনও সম্ভবত একটি বৈধ পয়েন্টার থাকতে পারে। অসামঞ্জস্যযুক্ত *pসমস্ত ধরণের জিনিস ওভাররাইট করে এবং কুরুচিপূর্ণ বাগগুলিতে নেতৃত্ব দেওয়া। বিশেষত যদি সংকলকটি ডিবাগ মোডে শূন্যের সাথে স্থানীয় ভেরিয়েবলগুলি সূচনা করে তবে একবার অপটিমাইজেশন চালু হয় না। রিলিজগুলি এলোমেলোভাবে ফুরিয়ে যাওয়ার সময় ডিবাগ বিল্ডগুলি বাগের কোনও চিহ্ন দেখায় না ...


2

যে পয়েন্টারটি সবেমাত্র NUL এ মুক্তি পেয়েছে তা সেট করা বাধ্যতামূলক নয় তবে একটি ভাল অনুশীলন। এইভাবে, আপনি 1) একটি মুক্ত পয়েন্ট ব্যবহার করে 2) এটিকে দু'বার মুক্ত করতে পারেন


2

NUL- এ একটি পয়েন্টার সেটিংস হ'ল পুনরায় তথাকথিত ডাবল-ফ্রি রক্ষা করা - যখন কোনও অবস্থাতেই ফ্রি () ঠিকানায় একই ঠিকানার জন্য ওই ঠিকানায় ব্লকটি পুনরায় প্রকাশ না করে বলা হয়।

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

সুতরাং সেরা অনুশীলন যদি না আপনি এখনই নিশ্চিত হন যে পয়েন্টারটি অবিলম্বে বা খুব শীঘ্রই ফ্রি () এর পরে স্কোপ ছেড়ে দেয় তবে সেই পয়েন্টারটি NULL এ সেট করে দেয় যাতে ফ্রি () আবারও বলা হলেও এটি এখন একটি নুল পয়েন্টার এবং অপরিজ্ঞাত আচরণের জন্য বলা হয় এড়ানো হয়।


2

ধারণাটি হ'ল যদি আপনি এটি মুক্ত করার পরে আর দীর্ঘকালীন-বৈধ পয়েন্টারকে অবজ্ঞা করার চেষ্টা করেন তবে আপনি নিঃশব্দে এবং রহস্যজনকভাবে শক্ত হয়ে (সেগফল্ট) ব্যর্থ হতে চান।

কিন্তু সতর্কতা অবলম্বন করা আবশ্যক. আপনি যদি NUL কে অবজ্ঞা করেন তবে সমস্ত সিস্টেমই সেগফোল্টের কারণ নয়। (কমপক্ষে কয়েকটি সংস্করণ) এআইএক্স, * (ইনট *) 0 == 0 এবং সোলারিসের এই এআইএক্স "বৈশিষ্ট্যটির সাথে optionচ্ছিক সামঞ্জস্য রয়েছে।"


2

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

যে কোনও সিস্টেমে এটিকে সঠিক জিনিসটিকে সহজতম করে তোলা এবং অসম্পূর্ণ পরিমাপের অপ্রতুল্য ব্যয় রয়েছে un সি-তে আমরা অত্যন্ত তীক্ষ্ণ, খুব শক্তিশালী সরঞ্জামগুলির একটি সেট অফার করছি, যা দক্ষ শ্রমিকের হাতে অনেকগুলি জিনিস তৈরি করতে পারে এবং যখন অনুচিতভাবে পরিচালনা করা হয় তখন সমস্ত ধরণের রূপক জখমের উপর চাপ দেয়। কিছু সঠিকভাবে বুঝতে বা ব্যবহার করা শক্ত। এবং মানুষ, প্রাকৃতিকভাবে ঝুঁকিপূর্ণ হওয়ায় এগুলি বিনা মূল্যে কল করার আগে নুল মানটির জন্য একটি পয়েন্টার পরীক্ষা করার মতো অযৌক্তিক কাজ করে ...

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

আপনি মান বিভাগের সাথে কেস করার আগে, বাগ ডেটা বেজটি চেষ্টা করে দেখতে চেষ্টা করুন যে, যদি কখনও অবৈধ পয়েন্টার মানগুলি সমস্যার কারণে লিখতে থাকে তবে often আপনি যদি সত্যই পার্থক্য করতে চান তবে আপনার উত্পাদন কোডের সর্বাধিক সাধারণ সমস্যা চিহ্নিত করুন এবং এটি প্রতিরোধের জন্য তিনটি উপায় প্রস্তাব করুন


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

2

দুটি কারণ রয়েছে:

ডাবল-মুক্ত হওয়ার সময় ক্রাশগুলি এড়িয়ে চলুন

একটি সদৃশ প্রশ্নে রাগেজ লিখেছেন ।

গ মধ্যে সর্বাধিক সাধারণ বাগটি ডাবল ফ্রি। মূলত আপনি এরকম কিছু করেন

free(foobar);
/* lot of code */
free(foobar);

এবং এটি শেষ পর্যন্ত খুব খারাপ, ওএস ইতিমধ্যে কিছু মুক্ত মেমরি মুক্ত করার চেষ্টা করে এবং সাধারণত এটি সেগফল্ট করে। সুতরাং ভাল অনুশীলনটি সেট করা হয় NULL, যাতে আপনি পরীক্ষা করতে পারেন এবং সত্যিকার অর্থে এই মেমরিটি মুক্ত করতে হবে কিনা তা পরীক্ষা করতে পারেন

if(foobar != NULL){
  free(foobar);
}

এছাড়াও লক্ষণীয় যে free(NULL) আপনি কিছু করতে পারবেন না যাতে আপনাকে বিবৃতি লিখতে হবে না। আমি আসলে কোনও ওএস গুরু নই তবে আমি বেশ সুন্দর এমনকি এখন বেশিরভাগ ওএস ডাবল ফ্রিতে ক্রাশ হবে।

আবর্জনা সংগ্রহের সমস্ত ভাষা (জাভা, ডটনেট) এ সমস্যা না হওয়ার এবং সামগ্রিকভাবে মেমরি পরিচালনা বিকাশকারীকে ছাড়তে না পেরে এই কারণেই এটি একটি প্রধান কারণও।

ইতিমধ্যে মুক্ত পয়েন্টার ব্যবহার করা এড়িয়ে চলুন

মার্টিন বনাম লুইস একটি অন্য উত্তরে লিখেছেন ।

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

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

শৈলীটি সম্পূর্ণ করতে, আপনাকে একটি সত্য পয়েন্টার মান নির্ধারণের আগে পয়েন্টারগুলি NUL এ সূচনা করতে হবে।


1

আপনার কাছে যেমন একটি গুণমানের আশ্বাসের দল রয়েছে, আমাকে QA সম্পর্কে একটি ছোটখাটো বক্তব্য যুক্ত করুন। সি এর জন্য কিছু অটোমেটেড কিউএ সরঞ্জাম মুক্ত পয়েন্টারগুলিকে "অকেজো অ্যাসাইনমেন্ট" হিসাবে অ্যাসাইনমেন্ট ফ্ল্যাগ করবে ptr। উদাহরণস্বরূপ গিম্পেল সফ্টওয়্যার থেকে পিসি-লিন্ট / ফ্লেক্সিলিন্ট বলেছেন tst.c 8 Warning 438: Last value assigned to variable 'nPtr' (defined at line 5) not used

বার্তাগুলি বাছাই করে দমন করার উপায় রয়েছে, সুতরাং আপনার টিমের সিদ্ধান্ত নেওয়া উচিত, তবে আপনি এখনও QA উভয় প্রয়োজনীয়তা পূরণ করতে পারেন।


1

সবসময় NULL এর সাথে পয়েন্টার ভেরিয়েবল ঘোষণা করার পরামর্শ দেওয়া হয় যেমন,

int *ptr = NULL;

আসুন বলুন, কাজ খুঁজছেন এরকম প্রতি নির্দেশ করা হয় 0x1000 মেমরি অ্যাড্রেস। ব্যবহার করার পর free(ptr), এটা সবসময় আবার ঘোষণা করে পয়েন্টার ভেরিয়েবল খর্ব করা সমীচীন হবে শূন্য । উদাহরণ:

free(ptr);
ptr = NULL;

না পুনরায় ঘোষণা তাহলে শূন্য , পয়েন্টার ভেরিয়েবল এখনও একই ঠিকানা (নির্দেশিত উপর রাখে 0x1000 ) এই পয়েন্টার ভেরিয়েবল একটি বলা হয় আনত পয়েন্টার । আপনি যদি অন্য পয়েন্টার ভেরিয়েবলটি নির্ধারণ করেন (আসুন বলুন, q ) এবং গতিশীলভাবে নতুন পয়েন্টারে ঠিকানা বরাদ্দ করেন তবে নতুন পয়েন্টার ভেরিয়েবল দ্বারা একই ঠিকানা ( 0x1000 ) নেওয়ার সুযোগ রয়েছে । ক্ষেত্রে, আপনি একই পয়েন্টার (ব্যবহার করেন তাহলে কাজ খুঁজছেন এরকম ) এবং মান আপডেট ঠিকানায় একই পয়েন্টার (দ্বারা নির্দিষ্ট কাজ খুঁজছেন এরকম ), তারপর প্রোগ্রাম জায়গা যেখানে একটি মান লেখা শেষ হবে কুই (নির্দেশ করা হয় যেহেতু পি এবং কুই হয় একই ঠিকানার দিকে ইঙ্গিত করা (0x1000 ))।

যেমন

*ptr = 20; //Points to 0x1000
free(ptr);
int *q = (int *)malloc(sizeof(int) * 2); //Points to 0x1000
*ptr = 30; //Since ptr and q are pointing to the same address, so the value of the address to which q is pointing would also change.

1

দীর্ঘ গল্প সংক্ষিপ্ত: আপনি যে ঠিকানাটি মুক্তি পেয়েছেন তা দুর্ঘটনাক্রমে (ভুল করে) অ্যাক্সেস করতে চান না। কারণ, আপনি ঠিকানাটি মুক্ত করার সময়, আপনি গাদাতে থাকা সেই ঠিকানাটি অন্য কোনও অ্যাপ্লিকেশনটিতে বরাদ্দ দেওয়ার অনুমতি দিন।

তবে, আপনি যদি NULL তে পয়েন্টার সেট না করেন এবং ভুল করে পয়েন্টারটিকে ডি-রেফারেন্স করার চেষ্টা করুন বা সেই ঠিকানার মান পরিবর্তন করতে পারেন; আপনি এটি এখনও করতে পারেন। আপনি লজিওলি চাইবেন এমন কিছু নয় S

আমি যে মেমরিটি ছেড়ে দিয়েছি তা এখনও কেন অ্যাক্সেস করতে পারি? কারণ: আপনার মেমরিটি মুক্ত থাকতে পারে তবে পয়েন্টার ভেরিয়েবলটিতে এখনও হিপ মেমরির ঠিকানা সম্পর্কে তথ্য ছিল। সুতরাং, একটি প্রতিরক্ষামূলক কৌশল হিসাবে, অনুগ্রহ করে সেট করুন।

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