সি বা সি ++ এ "নাল চেক" করার অর্থ কী?


21

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

  • নাল ঠিক কি?
  • "নাল পরীক্ষা করা" এর অর্থ কী?
  • আমার কি সবসময় নাল পরীক্ষা করা দরকার?

যে কোনও কোড উদাহরণগুলি অনেক প্রশংসিত হবে।


কখন
যাবেন

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

উত্তর:


26

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

একটি সাধারণ সমাধান যা অনেকগুলি ত্রুটি সনাক্ত করে তা হ'ল সমস্ত পয়েন্টার সেট করা যা কোনও কিছুর দিকে নির্দেশ করে না NULL(বা, সঠিক সি ++ তে 0), এবং পয়েন্টারটি অ্যাক্সেস করার আগে এটি পরীক্ষা করে। বিশেষত, সমস্ত পয়েন্টারগুলিকে NUL- এ সূচনা করা সাধারণ অনুশীলন (যদি আপনি তাদের ঘোষণার সময় ইতিমধ্যে তাদের নির্দেশ করার মতো কিছু না করেন) এবং আপনি deleteবা free()তাদের ( যখন তারা তত্ক্ষণাত সুযোগের বাইরে না যায়) এগুলি NULL এ সেট করুন । উদাহরণ (সি তে, তবে বৈধ সি ++):

void fill_foo(int* foo) {
    *foo = 23; // this will crash and burn if foo is NULL
}

আরও ভাল সংস্করণ:

void fill_foo(int* foo) {
    if (!foo) { // this is the NULL check
        printf("This is wrong\n");
        return;
    }
    *foo = 23;
}

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


3
@ মিঃলিস্টার আপনার অর্থ কি, নাল চেকগুলি সি ++ এ কাজ করে না? আপনি যখন এটি ঘোষণা করবেন তখন আপনাকে পয়েন্টারটি শূন্য করতে শুরু করতে হবে।
TZHX

1
আমার অর্থ হ'ল আপনাকে অবশ্যই পয়েন্টারটি NUL এ সেট করতে হবে বা এটি কাজ করবে না। এবং যদি আপনি মনে রাখেন , অন্য কথায় যদি আপনি জানেন যে পয়েন্টারটি নুল, তবে আপনাকে যাইহোক फिल_ফু কল করার প্রয়োজন হবে না। fill_foo চেক যদি পয়েন্টার একটি মান আছে, পয়েন্টার একটি হয়েছে থাকে না বৈধ মান। সি ++ এ, পয়েন্টারগুলির কোনও বৈধ মান থাকার কারণে NULL হওয়ার নিশ্চয়তা নেই।
মিস্টার লিস্টার

4
একটি দৃsert়তা () এখানে একটি ভাল সমাধান হতে পারে। "নিরাপদ" থাকার চেষ্টা করার কোনও অর্থ নেই। যদি NULL পাস করা হয় তবে এটি স্পষ্টতই ভুল, তবে প্রোগ্রামারকে পুরোপুরি সচেতন করার জন্য কেবল স্পষ্টভাবে ক্রাশ নয় কেন? (এবং উৎপাদনে, তাই না ব্যাপার কারণ আপনার থাকেন না, প্রমাণিত । যে কেউ কিছু fill_foo () শূন্য সঙ্গে ডাকব, ডান সত্যিই, এটা না যে কঠিন)
Ambroz Bizjak

7
এটি উল্লেখ করতে ভুলবেন না যে এই ফাংশনের আরও উন্নত সংস্করণে পয়েন্টারগুলির পরিবর্তে রেফারেন্সগুলি ব্যবহার করা উচিত, যা NUL চেকটি অপ্রচলিত করে।
ডক ব্রাউন

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

7

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

যদিও আমি নিজের পরামর্শের অংশটি এখানে যুক্ত করতে যাচ্ছি। নাল চেক এড়িয়ে চলুন। :) নাল চেক (এবং ডিফেন্সিভ প্রোগ্রামিং এর অন্যান্য ফর্ম) বিশৃঙ্খলা কোড আপ, এবং প্রকৃতপক্ষে এটি অন্যান্য ত্রুটি-পরিচালনা কৌশলগুলির তুলনায় আরও ত্রুটি প্রবণ করে তোলে।

আমার প্রিয় কৌশলটি যখন পয়েন্টারগুলি অবজেক্টের কথা আসে তখন হ'ল নাল অবজেক্ট প্যাটার্নটি ব্যবহার করা । এর অর্থ একটি (পয়েন্টার - বা আরও ভাল, একটি রেফারেন্স) শূন্যের পরিবর্তে খালি অ্যারে বা তালিকা ফিরে আসা, বা শূন্যের পরিবর্তে একটি ফাঁকা স্ট্রিং (""), অথবা স্ট্রিং "0" (বা "কিছুই না" সমান কিছু) "প্রসঙ্গে) যেখানে আপনি এটি পূর্ণসংখ্যায় পার্স করার আশা করছেন to

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

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


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

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

অ্যালগরিদমের যদি কিছু করার থাকে না, তবে আপনি কেন এটি কল করছেন? এবং কারণ আপনি প্রথম স্থানে একে ডাকতে চেয়েছিলেন পারে , কারণ এটি গুরুত্বপূর্ণ কিছু না
ডেডএমজি

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

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

4

নাল পয়েন্টার মান একটি ভাল সংজ্ঞায়িত "কোথাও" প্রতিনিধিত্ব করে না; এটি একটি অবৈধ পয়েন্টার মান যা অন্য কোনও পয়েন্টার মানের সাথে অসম তুলনা করার গ্যারান্টিযুক্ত। কোনও শূন্য পয়েন্টারকে অবজ্ঞার চেষ্টা করার ফলে অপরিজ্ঞাত আচরণের ফলাফল হয় এবং এটি সাধারণত রানটাইম ত্রুটির দিকে পরিচালিত করে, সুতরাং আপনি নিশ্চিত করতে চান যে কোনও পয়েন্টারটি অবলম্বন করার চেষ্টা করার আগে নাল নয়। বেশ কয়েকটি সি এবং সি ++ গ্রন্থাগার ফাংশন ত্রুটির শর্তটি বোঝাতে একটি নাল পয়েন্টার ফেরত দেবে। উদাহরণস্বরূপ, লাইব্রেরির ফাংশনটি mallocনাল পয়েন্টার মানটি ফিরিয়ে দেবে যদি এটি অনুরোধ করা বাইটের সংখ্যা বরাদ্দ করতে না পারে এবং সেই পয়েন্টারের মাধ্যমে মেমরি অ্যাক্সেসের চেষ্টা করা (সাধারণত) রানটাইম ত্রুটির দিকে পরিচালিত করে:

int *p = malloc(sizeof *p * N);
p[0] = ...; // this will (usually) blow up if malloc returned NULL

সুতরাং আমাদের নিশ্চিত করা দরকার যে mallocকলটি pNULL এর বিপরীতে মূল্য পরীক্ষা করে সফল হয়েছে :

int *p = malloc(sizeof *p * N);
if (p != NULL) // or just if (p)
  p[0] = ...;

এখন, আপনার মোজাগুলিতে এক মিনিট আটকে থাকুন, এটি কিছুটা গন্ডগোল পেতে চলেছে।

একটি নাল পয়েন্টার মান এবং একটি নাল পয়েন্টার ধ্রুবক আছে , এবং দুটি অবশ্যই অভিন্ন নয় the নাল পয়েন্টার মান হ'ল অন্তর্নিহিত আর্কিটেকচার "কোথাও" উপস্থাপন করতে যা মান ব্যবহার করে। এই মান 0x00000000, বা 0xFFFFFFFF, বা 0xDEADBEEF, বা সম্পূর্ণ আলাদা কিছু হতে পারে। মনে করবেন না যে নাল পয়েন্টার মান সর্বদা 0 থাকে।

নাল পয়েন্টার ধ্রুবক , OTOH সর্বদা 0-মানযুক্ত ইন্টিগ্রাল এক্সপ্রেশন। আপনার সোর্স কোড হিসাবে , 0 (বা কোনও অখণ্ড এক্সপ্রেশন যা 0 এ মূল্যায়ন করে) একটি নাল পয়েন্টার উপস্থাপন করে। সি এবং সি উভয়ই নাল পয়েন্টার ধ্রুবক হিসাবে ন্যূনল ম্যাক্রোকে সংজ্ঞায়িত করে। যখন আপনার কোডটি সংকলিত হবে, নাল পয়েন্টার ধ্রুবকটি উত্পাদিত মেশিন কোডে উপযুক্ত নাল পয়েন্টার মানের সাথে প্রতিস্থাপন করা হবে ।

এছাড়াও, সচেতন থাকুন যে NUL অনেকগুলি সম্ভাব্য অবৈধ পয়েন্টার মানেরগুলির মধ্যে একটি; আপনি যদি কোনও অটো পয়েন্টার ভেরিয়েবলকে স্পষ্টভাবে আরম্ভ না করে ঘোষণা করেন, যেমন

int *p;

ভেরিয়েবেলে প্রাথমিকভাবে সঞ্চিত মানটি অনির্দিষ্ট হয় এবং এটি কোনও বৈধ বা অ্যাক্সেসযোগ্য মেমরি ঠিকানার সাথে মিল নাও পারে। দুর্ভাগ্যক্রমে, কোনও এনওএলএল পয়েন্টার মানটি ব্যবহারের চেষ্টা করার আগে বৈধ কিনা তা বলার কোনও (পোর্টেবল) উপায় নেই। সুতরাং যদি আপনি পয়েন্টারগুলির সাথে কাজ করে থাকেন তবে সাধারণত আপনি যখন তাদের ঘোষণা করবেন তখন তাদের স্পষ্টভাবে NULL এ সূচনা করা এবং যখন তারা সক্রিয়ভাবে কোনও কিছুর দিকে ইঙ্গিত করছে না তখন সেগুলি NUL এ সেট করা ভাল idea

নোট করুন যে এটি সি ++ এর চেয়ে সি-তে আরও একটি ইস্যু; আইডোম্যাটিক সি ++ এর বেশি পয়েন্টার ব্যবহার করা উচিত নয়।


3

কয়েকটি পদ্ধতি রয়েছে, সমস্ত মূলত একই জিনিসটি করে।

int * foo = NULL; // কখনও কখনও NUL এর পরিবর্তে 0x00 বা 0 বা 0L তে সেট করুন

নাল চেক (পয়েন্টারটি নাল কিনা তা পরীক্ষা করুন), সংস্করণ এ

যদি (foo == নাল)

নাল চেক, সংস্করণ বি

যদি (! foo) // যেহেতু NULL 0 হিসাবে সংজ্ঞায়িত করা হয়েছে, foo নাল পয়েন্টার থেকে কোনও মান ফেরত দেবে

নাল চেক, সংস্করণ সি

যদি (foo == 0)

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


2

আপনি না। সি ++ তে পয়েন্টার ব্যবহারের একমাত্র কারণ হ'ল আপনি স্পষ্টভাবে নাল পয়েন্টারগুলির উপস্থিতি চান; অন্যথায়, আপনি একটি রেফারেন্স নিতে পারেন, যা উভয় শব্দার্থগতভাবে ব্যবহার করা সহজ এবং নন-নালকে গ্যারান্টি দেয়।


1
@ জেমস: কার্নেল মোডে 'নতুন'?
নেমানজা ত্রিফুনোভিচ

1
@ জেমস: সি ++ এর একটি বাস্তবায়ন যা উল্লেখযোগ্য সংখ্যাগরিষ্ঠ সি ++ কোডারদের উপভোগ করে এমন ক্ষমতাগুলির প্রতিনিধিত্ব করে। এর মধ্যে সমস্ত সি ++ 03 ভাষা বৈশিষ্ট্য (ব্যতীত export) এবং সমস্ত সি ++ 03 লাইব্রেরি বৈশিষ্ট্য এবং টিআর 1 এবং সি ++ 11 এর একটি ভাল অংশ রয়েছে।
ডেডএমজি

5
আমি আশা করি লোকেরা এটি না বলে যে "রেফারেন্সগুলি অ-নালার গ্যারান্টি দেয়।" তারা না। নাল পয়েন্টার হিসাবে নাল রেফারেন্স উত্পন্ন করা সহজ এবং তারা একইভাবে প্রচার করে।
mjfgates

2
@ স্টারগাজার: আপনি যখন ভাষা ডিজাইনারদের এবং ভাল অনুশীলনের পরামর্শ দেবেন সেভাবে আপনি যখন সরঞ্জামগুলি ব্যবহার করেন তখন প্রশ্নটি 100% অপ্রয়োজনীয়।
ডেডএমজি

2
@ ডিড এমএমজি, এটি নিরর্থক কিনা তা বিবেচ্য নয়। আপনি প্রশ্নের উত্তর না । আমি আবার বলব: -১।
রিভালক

-1

আপনি যদি NULL মানটি পরীক্ষা না করেন, বিশেষত, যদি এটি কোনও কাঠামোর নির্দেশক হয় তবে আপনি সম্ভবত একটি সুরক্ষিত দুর্বলতার মুখোমুখি হন - NULL পয়েন্টার ডিरेফারেন্স। নুল পয়েন্টার অবলম্বন হতে পারে এমন আরও কিছু গুরুতর সুরক্ষা দুর্বলতা যেমন বাফার ওভারফ্লো, রেস শর্ত ... হতে পারে যা আক্রমণকারী আপনার কম্পিউটারের নিয়ন্ত্রণ নিতে দেয়।

মাইক্রোসফ্ট, ওরাকল, অ্যাডোব, অ্যাপল এর মতো অনেক সফটওয়্যার বিক্রেতার ... এই সুরক্ষা দুর্বলতাগুলি ঠিক করতে সফ্টওয়্যার প্যাচ প্রকাশ করুন। আমি মনে করি আপনার প্রতিটি পয়েন্টারের নল মানটি পরীক্ষা করা উচিত :)

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