সি ++ খারাপ অভ্যাসে দাবী () ব্যবহার করা হচ্ছে?


94

রিলিজ বিল্ডগুলির কার্যকারিতা প্রভাবিত না করে ডিবাগিং সহজ করার জন্য আমি আমার সি ++ কোডে প্রচুর পরিমাণ যুক্তি যুক্ত করার প্রবণতা রাখি। এখন, assertসি ++ প্রক্রিয়াগুলি মাথায় না রেখে একটি খাঁটি সি ম্যাক্রো।

অন্যদিকে সি ++ সংজ্ঞায়িত করে std::logic_error, যার অর্থ প্রোগ্রামের যুক্তিতে কোনও ত্রুটি রয়েছে (তাই নাম) cases উদাহরণ নিক্ষেপ করা কেবলমাত্র নিখুঁত, আরও সি ​​++ ইশ বিকল্প হতে পারে assert

সমস্যাটি হ'ল assertএবং abortউভয়ই ডেস্ট্রাক্টরদের কল না করেই প্রোগ্রামটি তত্ক্ষণাত বন্ধ করে দেন, সুতরাং ক্লিনআপটি এড়িয়ে যান, অন্যদিকে ম্যানুয়ালি একটি ব্যতিক্রম নিক্ষেপ করা অপ্রয়োজনীয় রানটাইম ব্যয়কে যুক্ত করে। এর চারপাশে একটি উপায় একটি নিজস্ব দৃser় ম্যাক্রো তৈরি করবে SAFE_ASSERT, যা কেবল সি পালকের মতো কাজ করে তবে ব্যর্থতার ক্ষেত্রে ব্যতিক্রম ছুঁড়ে ফেলে।

এই সমস্যা সম্পর্কে আমি তিনটি মতামত ভাবতে পারি:

  • সি এর দৃ to়তার সাথে লেগে থাকুন। যেহেতু প্রোগ্রামটি তত্ক্ষণাত বন্ধ হয়ে গেছে, পরিবর্তনগুলি সঠিকভাবে তালিকাভুক্ত করা হয়েছে কিনা তা বিবেচ্য নয়। এছাড়াও, #defineসি ++ তে এস ব্যবহার করা ঠিক ততটাই খারাপ।
  • একটি ব্যতিক্রম নিক্ষেপ করুন এবং এটি মূল () তে ধরুন । প্রোগ্রামের কোনও রাজ্যে ডেস্ট্রাক্টরদের এড়িয়ে যাওয়ার কোডকে দেওয়া খারাপ অভ্যাস এবং এটি সর্বদা এড়ানো উচিত এবং তাই () সমাপ্ত করার জন্য কলগুলিও রয়েছে। যদি ব্যতিক্রম ছুঁড়ে দেওয়া হয় তবে তাদের অবশ্যই ধরা পড়বে।
  • একটি ব্যতিক্রম নিক্ষেপ করুন এবং এটি প্রোগ্রামটি শেষ করতে দিন। কোনও প্রোগ্রামের সমাপ্তি ব্যতিক্রম ঠিক আছে, এবং এর কারণে NDEBUGএটি কোনও রিলিজ বিল্ডে কখনও ঘটবে না। ক্যাচিং অপ্রয়োজনীয় এবং অভ্যন্তরীণ কোডটির বাস্তবায়ন বিশদটি প্রকাশ করে main()

এই সমস্যার একটি নির্দিষ্ট উত্তর আছে? কোন পেশাদার রেফারেন্স?

সম্পাদিত: এড়িয়ে যাওয়া ধ্বংসকারীরা অবশ্যই কোনও অপরিজ্ঞাত আচরণ নয়।


22
না, সত্যিই, logic_errorলজিক ত্রুটি। প্রোগ্রামটির যুক্তিতে একটি ত্রুটি বলা হয় একটি বাগ। আপনি ব্যতিক্রম ছুঁড়ে দিয়ে বাগ সমাধান করবেন না।
আর মার্টিনহো ফার্নান্দেস

4
জোর, ব্যতিক্রম, ত্রুটি কোড। প্রত্যেকের একটি সম্পূর্ণ স্বতন্ত্র ব্যবহারের কেস রয়েছে এবং যেখানে অন্যের প্রয়োজন সেখানে আপনার ব্যবহার করা উচিত নয়।
কেরেরেক এসবি

4
static_assertআপনার কাছে যদি এটি উপলভ্য থাকে তবে আপনি যেখানে এটি উপযুক্ত তা ব্যবহার করার বিষয়টি নিশ্চিত করুন ।
ফ্লেক্সো

4
@ ত্রিশন আমি দেখতে পাচ্ছি না যে কীভাবে সাহায্য করে। তুমি ফেলে দেবে std::bug?
আর মার্টিনহো ফার্নান্দেস

4
@ ত্রিশন: তা করবেন না। ব্যতিক্রমগুলি ডিবাগিংয়ের জন্য নয়। কেউ হয়ত ব্যতিক্রমটি ধরছে। ফোন করার সময় ইউবি সম্পর্কে কোনও চিন্তা করার দরকার নেই std::abort(); এটি কেবলমাত্র একটি সিগন্যাল উত্থাপন করবে যা প্রক্রিয়াটি শেষ হতে দেয়।
কেরেরেক এসবি

উত্তর:


74

জোর দেওয়া সি ++ কোডে সম্পূর্ণ উপযুক্ত। ব্যতিক্রম এবং অন্যান্য ত্রুটি পরিচালনার পদ্ধতিগুলি সত্যিকারের দাবিগুলির মতো নয় for

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

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


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

এছাড়াও যদি আপনি একটি ব্যতিক্রমের শর্তে দৃser়তার সাথে প্রয়োগ করেন তবে সম্ভবত এটি ধরা পড়ে এবং পরিচালনা করা যেতে পারে যদিও এটি দৃser়তার মূল উদ্দেশ্যটির সাথে স্ববিরোধী।


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

101
  • ডিবাগিংয়ের জন্য জোর দেওয়া হয়েছে । আপনার শিপড কোড ব্যবহারকারীর এগুলি কখনও দেখা উচিত নয়। যদি একটি দৃ hit়তা আঘাত করা হয়, আপনার কোডটি ঠিক করা দরকার।

    CWE-617: পুনরুদ্ধারযোগ্য দৃ .়তা

প্রোডাক্টটিতে একটি দৃsert় () বা অনুরূপ বিবৃতি রয়েছে যা আক্রমণকারী দ্বারা চালিত হতে পারে, যা অ্যাপ্লিকেশন থেকে প্রস্থান বা অন্য আচরণের দিকে পরিচালিত করে যা প্রয়োজনের চেয়ে গুরুতর হয়।

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

উদাহরণস্বরূপ, যদি কোনও সার্ভার একাধিক একযোগে সংযোগগুলি পরিচালনা করে এবং একটি সিলেক্ট () একটি সংযোগ ঘটে যা অন্য সমস্ত সংযোগগুলি বাদ দেওয়ার কারণ হয়ে থাকে, এটি একটি পৌঁছনীয় দৃ as়তা যা পরিষেবার অস্বীকারের দিকে পরিচালিত করে।

  • ব্যতিক্রম ব্যতিক্রমী পরিস্থিতিতে । যদি কোনওটির মুখোমুখি হয়, ব্যবহারকারী তার পছন্দমতো করতে সক্ষম হবেন না, তবে অন্য কোথাও আবার শুরু করতে সক্ষম হবেন।

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


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

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

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

14

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


আমারও অনুরূপ পন্থা আছে। আমি যুক্তির জন্য দৃser়তাগুলি ব্যবহার করি যা সম্ভবত স্থানীয়ভাবে সঠিক হওয়া উচিত (যেমন লুপ আক্রমণকারী)। ব্যতিক্রমগুলি যেখানে ননলোকাল (বাহ্যিক) পরিস্থিতি দ্বারা কোডটিতে কোনও যুক্তি ত্রুটি বাধ্য করা হয়েছিল Ex
স্প্রেফ

যদি কোনও দৃ f়তা ব্যর্থ হয় তবে এর অর্থ প্রোগ্রামটির অংশের যুক্তিটি নষ্ট হয়ে গেছে। একটি ব্যর্থ বক্তব্য অগত্যা বোঝায় না যে কিছুই সম্পাদন করা যায় না। একটি ভাঙা প্লাগইন সম্ভবত একটি সম্পূর্ণ ওয়ার্ড প্রসেসর বাতিল করা উচিত নয়।
ডিমনসপ্রিং

13

Alling Abort () এর কারণে ডেস্ট্রাক্টর চালানো অপরিবর্তিত আচরণ নয়!

যদি এটি হয়, তবে এটিরও কল করা অপরিজ্ঞাত আচরণ হবে std::terminate()এবং তাই এটি সরবরাহ করার কী দরকার?

assert() সি ++ তে ঠিক যেমন সি হিসাবে কার্যকর, জোর দেওয়া ত্রুটি পরিচালনার জন্য নয়, তারা তত্ক্ষণাত প্রোগ্রামটি বাতিল করার জন্য।


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

এবং assertকল করতে সংজ্ঞায়িত হয় abort(যখন শর্তটি মিথ্যা থাকে)। ব্যতিক্রম ছোঁড়ার ক্ষেত্রে, না, এটি সর্বদা উপযুক্ত নয়। কিছু জিনিস কলকারী পরিচালনা করতে পারবেন না। তৃতীয় পক্ষের লাইব্রেরি ফাংশনে কোনও লজিক বাগ পুনরুদ্ধারযোগ্য, বা দুর্নীতিগ্রস্থ ডেটা স্থির করা যায় কিনা তা কলার নির্ধারণ করতে পারে না।
জোনাথন ওয়েকেলি

6

আইএমএইচও, দাবিগুলি শর্তাদি যাচাই করার জন্য যা যদি লঙ্ঘন করা হয় তবে অন্য সমস্ত কিছু আজেবাজে করে। এবং তাই আপনি তাদের কাছ থেকে পুনরুদ্ধার করতে পারবেন না বরং পুনরুদ্ধার অপ্রাসঙ্গিক।

আমি তাদের 2 টি বিভাগে গ্রুপ করব:

  • বিকাশকারী পাপ (যেমন একটি সম্ভাব্যতা ফাংশন যা নেতিবাচক মানগুলি দেয়):

ভাসা সম্ভাবনা () {রিটার্ন -1.0; }

দাবি (সম্ভাবনা ()> 0.0)

  • মেশিনটি নষ্ট হয়ে গেছে (যেমন আপনার প্রোগ্রামটি চালিত করে এমন মেশিনটি খুব ভুল):

int x = 1;

দৃsert় (x> 0);

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

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


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