সি লাইব্রেরির ফাংশনের পিছনে যুক্তি কখনই শূন্যে স্থির করে না


9

সি স্ট্যান্ডার্ড আদেশ দেয় যে কোনও সি স্ট্যান্ডার্ড লাইব্রেরি ফাংশন errnoশূন্যে সেট করা হবে না। ঠিক এটাই কেন?

আমি বুঝতে পারি এটি বেশ কয়েকটি ফাংশন কল করার জন্য দরকারী এবং কেবল errnoশেষের পরে পরীক্ষা করা - উদাহরণস্বরূপ:

errno = 0;
double x = strtod(str1, NULL);
long y = strtol(str2, NULL);
if (errno)
    // either "strtod" or "strtol" failed
else
    // both succeeded

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

আমি বিভিন্ন সি রেশনাল ডকুমেন্টগুলি সন্ধান করার চেষ্টা করেছি, তবে তাদের অনেকের কাছে খুব বেশি বিশদ নেই <errno.h>


1
আমার ধারণা এটি "আপনি যা চান না তার জন্য অর্থ প্রদান করবেন না"। আপনি যদি যত্নশীল হন তবে আপনি errnoসর্বদা নিজেকে শূন্যে সেট করতে পারেন।
কেরেরেক এসবি 21

2
সচেতন হওয়ার মতো আরও কিছু বিষয় হ'ল কোনও ফাংশনটি errnoসাফল্য পেলেও একটি শূন্য-মান নির্ধারণ করতে পারে। (এটি হয়ত অন্য কোনও ফাংশন কল করতে পারে যা ব্যর্থ হয়, তবে এটি বাহ্যিক কার্যক্রমে ব্যর্থতা বলে মনে করে না))
কিথ থম্পসন

উত্তর:


10

C লাইব্রেরি সেট করেনি errnoঐতিহাসিক কারণে 0 1 । পসিক্স আর দাবি করে না যে এর লাইব্রেরিগুলি সাফল্যের ক্ষেত্রে মানকে পরিবর্তন করবে না এবং নতুন লিনাক্স ম্যান পৃষ্ঠাটি এটিerrno.h প্রতিফলিত করে:

<errno.h>হেডার ফাইলটি পূর্ণসংখ্যা পরিবর্তনশীল সংজ্ঞায়িত errno, যা সিস্টেম কল ও একটি ত্রুটির ঘটনা মধ্যে কিছু লাইব্রেরি ফাংশন ইঙ্গিত কি ভুল হয়েছে দ্বারা সেট করা হয়। কলটির রিটার্ন মান কোনও ত্রুটি নির্দেশ করলেই এর মূল্য তাত্পর্যপূর্ণ (যেমন, -1বেশিরভাগ সিস্টেম কল থেকে ; -1বা NULLবেশিরভাগ লাইব্রেরি ফাংশন থেকে); একটি ফাংশন যা সফল হয় তাকে পরিবর্তনের অনুমতি দেওয়া হয় errno

ANSI সি নীতি বলে যে, কমিটি অনুভূত এটা গ্রহণ করেন এবং ব্যবহারের বিদ্যমান অনুশীলনের প্রমিত আরো ব্যবহারিক ছিল errno

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

errnoসেট হয়ে গেছে কিনা তা যাচাই করার বাইরে প্রায় সর্বদা ত্রুটির জন্য চেক করার একটি উপায় রয়েছে । যদি চেক করা হচ্ছে errnoপেয়েছিলাম সেট সবসময় নির্ভরযোগ্য নয়, যেহেতু কিছু কল ত্রুটি কারণ পেতে একটি পৃথক এপিআই কলিং প্রয়োজন। উদাহরণস্বরূপ, ferror()যদি আপনি fread()বা থেকে একটি সংক্ষিপ্ত ফলাফল পান তবে একটি ত্রুটি পরীক্ষা করার জন্য ব্যবহৃত হয় fwrite()

যথেষ্ট উত্সাহের ব্যাপার হল ব্যবহার আপনার উদাহরণ strtod()ক্ষেত্রে এক সেটিং কোথায় errno0 সামনে কল প্রয়োজনীয় সঠিকভাবে সনাক্ত করতে যদি কোনো ত্রুটি ঘটেছে। সমস্ত strto*()স্ট্রিং টু নং ফাংশনের এই প্রয়োজনীয়তা রয়েছে কারণ বৈধ ফেরতের মান এমনকি ত্রুটির পরেও ফিরে আসে is

errno = 0;
char *endptr;
double x = strtod(str1, &endptr);
if (endptr == str1) {
    /*...parse error */
} else if (errno == ERANGE) {
    if (x == 0) {
        /*...underflow */
    } else if (x == HUGE_VAL) {
        /*...positive overflow */
    } else if (x == -HUGE_VAL) {
        /*...negative overflow */
    } else {
        /*...unknown range error? */
    }
}

উপরের কোডটি strtod()লিনাক্সে দলিল হিসাবে ব্যবহারের উপর ভিত্তি করে । সি স্ট্যান্ডার্ডটি কেবল এই শর্ত দেয় যে আন্ডারফ্লো সবচেয়ে ক্ষুদ্র ধনাত্মকটির চেয়ে বেশি কোনও মান প্রদান করতে পারে না double, এবং errnoসেটাকে 2 টিERANGE নির্ধারিত বাস্তবায়ন হিসাবে সেট করা হয় কিনা ।

প্রকৃতপক্ষে একটি বিস্তৃত সার্টের পরামর্শমূলক লিখন-আপ রয়েছে যা errnoএকটি লাইব্রেরি কল করার আগে সর্বদা 0 তে সেট করার পরামর্শ দেয় এবং কলটির পরে এর মান পরীক্ষা করে ব্যর্থতা দেখা দেয় । কারণ errnoকলটি 3 টি সফল হলেও কিছু লাইব্রেরি কল সেট করবে ।

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


১. পূর্বে আমি দাবি করেছি যে এটি পূর্ববর্তী কল থেকে কোনও ত্রুটিটি মাস্কিং এড়ানোর জন্য। এই দাবিটি সমর্থন করার জন্য আমি কোনও প্রমাণ পাই না। আমারও বোগাসের printf()উদাহরণ ছিল।
২. এটি নির্দেশ করার জন্য @ চাক্সকে ধন্যবাদ। রেফারেন্সটি C.11 §7.22.1.3 ¶10।
৩.কীথথম্পসন একটি মন্তব্যে প্রেরিত।


মাইনর ইস্যু: এটি আন্ডারফ্লোতে অ 0-এর ফলাফল হতে পারে বলে মনে হয়: "ফাংশনগুলি এমন একটি মান প্রদান করে যার প্রস্থতা" C11 7.22.1.3.10 "র রিটার্ন টাইপের সামান্যতম স্বাভাবিক ধনাত্মক সংখ্যার চেয়ে বেশি নয়।
chux - মনিকা

@ চিচস: ধন্যবাদ আমি একটি সম্পাদনা করব। সেটিং যেহেতু errnoকরতে ERANGEunderflow ক্ষেত্রে সংজ্ঞায়িত বাস্তবায়ন হয়, আসলে কোন underflow সনাক্ত করতে পোর্টেবল উপায়। আমার কোডটি আমার সিস্টেমে লিনাক্স ম্যান পৃষ্ঠায় যা পেয়েছিল তা অনুসরণ করেছিল।
jxh

strto*ফাংশন সম্পর্কে আপনার মন্তব্য হ'ল কেন আমার জিজ্ঞাসা করা হয়েছে যে আমার উদাহরণটি খারাপ অভ্যাস হিসাবে বিবেচিত হবে, তবে এটি একমাত্র উপায় যা errnoশূন্যে সেট না হওয়া কার্যকর হবে, এমনকি প্রয়োগও হবে।

@ ড্রু ম্যাকগোউইন: আমি অনুমান করি যে আপনি কেবলমাত্র পয়েন্ট নিতে পারেন তা errnoসাফল্যের ক্ষেত্রেও সেট হয়ে যেতে পারে, সুতরাং এটি ঠিক করা সত্যটি ব্যবহার করা আসলেই কোনও ত্রুটি ঘটেছে এমন যথেষ্ট সঠিক সূচক নয়। আপনাকে কোনও ত্রুটি ঘটেছে কি না তা জানতে তাদের পৃথক কলের ফলাফলগুলি পরীক্ষা করতে হবে।
জেএক্সএইচ

1

আপনি যদি সত্যিই যত্ন নেন তবে আপনি উভয় ফাংশন কলের জন্য ত্রুটি পরীক্ষা করতে পারেন।

errno = 0;
double x = strtod(str1, NULL);
if (errno)
    // strtod"  failed
else
    // "strtod" succeeded

long y = strtol(str2, NULL);
if (errno)
    // "strtol" failed
else
    // "strtol" succeeded

যেহেতু আমরা কখনই জানি না যে ম্যাক ফাংশনটিকে কোনও প্রক্রিয়াতে ডাকা হয়, তাই লিব কীভাবে প্রতিটি ফাংশন কলের জন্য ঠিক করে দিতে পারে?


1

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

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