নাল পয়েন্টার যুক্তি এবং অসম্ভব পোস্টকন্ডিশনগুলির সাথে মান ব্যতিক্রমগুলি তৈরি করুন


9

নিম্নলিখিত প্রোগ্রাম বিবেচনা করুন:

#include<stdexcept>
#include<iostream>

int main() {
    try {
        throw std::range_error(nullptr);
    } catch(const std::range_error&) {
        std::cout << "Caught!\n";
    }
}

Libstdc ++ কল সহ জিসিসি এবং কলঙ্ক std::terminateএবং বার্তাটি সহ প্রোগ্রামটি বাতিল করে দিন

terminate called after throwing an instance of 'std::logic_error'
  what():  basic_string::_S_construct null not valid

ব্যতিক্রম নির্মাণে libc ++ segfaults সঙ্গে ঝাঁকুনি।

গডবোল্ট দেখুন ।

সংকলকরা কি মান-অনুসারে আচরণ করছে? স্ট্যান্ডার্ডের [ডায়াগনস্টিক্স.আরঞ্জ.অররর] (সি +++ এন 4659) এর প্রাসঙ্গিক বিভাগটি বলে যে std::range_errorএকটি const char*নির্মাণকারী ওভারলোড রয়েছে যা ওভারলোডের চেয়ে বেশি পছন্দ করা উচিত const std::string&। বিভাগটি কনস্ট্রাক্টরের উপর কোনও পূর্বশর্তও বর্ণনা করে না এবং কেবল পোস্টকন্ডিশনকেই জানিয়েছে

Postconditions : strcmp(what(), what_­arg) == 0

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


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

সুতরাং, এটি সত্য বলে ধরে নিচ্ছি, আমি কীভাবে মানকে এই অনির্ধারিত আচরণকে বোঝায় সেদিকেই প্রশ্নটি আরও केन्द्रিত করতে চাই। এটি কি পোস্টকন্ডিশনের অসম্ভবতা থেকে অনুসরণ করে যে কলটিতেও অনির্ধারিত আচরণ রয়েছে বা পূর্বশর্তটি সহজেই ভুলে গিয়েছিল?


এই প্রশ্নের দ্বারা অনুপ্রাণিত ।


মনে হচ্ছে স্ট্যান্ড :: রেঞ্জ_অররারের রেফারেন্সের মাধ্যমে জিনিসগুলি সংরক্ষণ করার অনুমতি দেওয়া হয়েছে, তাই আমি অবাক হব না। পাস হয়ে what()গেলে কল করা nullptrসমস্যার কারণ হতে পারে।
চিপস্টার

@ শিপস্টার আপনি ঠিক কী বলতে চাইছেন তা আমি নিশ্চিত নই, তবে এই সম্পর্কে আবার চিন্তাভাবনা করার পরে, আমি মনে করি এটি অবশ্যই সংজ্ঞায়িত আচরণ হতে হবে। প্রমিত শব্দটি কীভাবে অপরিজ্ঞাত আচরণকে বোঝায় তার উপর এটি আরও ফোকাস করার জন্য আমি আমার প্রশ্ন সম্পাদনা করেছি ।
আখরোট

যদি nullptrপাস হয়ে যায় তবে আমি মনে করব যে what()মানটি পেতে কোনও সময় এটির অবনতি করতে হবে। এটি একটি ডিগ্রিফারেন্সিং হবে nullptr, যা সর্বোপরি সমস্যাযুক্ত এবং ক্র্যাশ করার জন্য সবচেয়ে খারাপ এটি।
চিপস্টার

আমি রাজি, যদিও। এটি অবশ্যই অপরিবর্তিত আচরণ হতে হবে। তবে, কেন আমার দক্ষতার বাইরে তা ব্যাখ্যা করে এটিকে পর্যাপ্ত উত্তরে রেখে দেওয়া।
চিপস্টার

আমি মনে করি এটি উদ্দেশ্যযুক্ত যে এটি পূর্ব শর্ত যে যুক্তিটি একটি বৈধ সি স্ট্রিংকে নির্দেশ করে, যেহেতু strcmpএর মান বর্ণনা করতে ব্যবহৃত হয় what_argসি স্ট্যান্ডার্ড থেকে প্রাসঙ্গিক বিভাগটি যাইহোক বলে, যা এর স্পেসিফিকেশন দ্বারা উল্লেখ করা হয় <cstring>। অবশ্যই শব্দবন্ধ পরিষ্কার হতে পারে।
এলএফ

উত্তর:


0

ডক থেকে :

যেহেতু স্ট্যান্ড :: রেঞ্জ_অরআর অনুলিপি করার ব্যতিক্রম ছড়িয়ে দেওয়ার অনুমতি নেই, এই বার্তাটি সাধারণত অভ্যন্তরীণভাবে পৃথক-বরাদ্দ রেফারেন্স-গণনা করা স্ট্রিং হিসাবে সংরক্ষণ করা হয়। এই কারণেই এখানে কোনও নির্মাতা স্টাডি :: স্ট্রিং ও& গ্রহণ করছেন না: এটি যেভাবেই কন্টেন্টটি অনুলিপি করতে হবে।

এটি দেখায় কেন আপনি সেগফল্ট পান, এপিআই সত্যই এটি একটি সত্যিকারের স্ট্রিং হিসাবে বিবেচনা করে। সিপিতে সাধারণভাবে যদি কিছু optionচ্ছিক হয় তবে সেখানে একটি ওভারলোডেড কনস্ট্রাক্টর / ফাংশন থাকবে যা এটির প্রয়োজন হয় না তা গ্রহণ করে না। সুতরাং nullptrএমন কোনও ফাংশনের জন্য পাস করা যা alচ্ছিক হতে পারে এমন কোনও বিষয় নথিভুক্ত করে না এটি অপরিজ্ঞাত আচরণ হতে চলেছে। সাধারণত এপিআই সি স্ট্রিং ব্যতীত পয়েন্টার নেয় না। সুতরাং আইএমএইচও এটি কোনও ফাংশনটির অপরিবর্তিত const char *আচরণ হিসাবে প্রত্যাশা করে যে নালপ্টর পাস করা নিরাপদ । আরও নতুন এপিআই std::string_viewসেই ক্ষেত্রে পছন্দ করতে পারে ।

হালনাগাদ:

সাধারণত একটি সি ++ এপিআই এনওএলএল গ্রহণ করার জন্য একটি পয়েন্টার গ্রহণ করে ধরে নেওয়া ন্যায়সঙ্গত। তবে সি স্ট্রিং একটি বিশেষ ক্ষেত্রে। যতক্ষণ না std::string_view, এগুলি দক্ষতার সাথে পাস করার আর ভাল উপায় ছিল না। কোনও এপিআই গ্রহণযোগ্যতার জন্য সাধারণভাবে const char *, অনুমানটি হ'ল এটি একটি বৈধ সি স্ট্রিং হওয়া উচিত। অর্থাত্‍ একটি ক্রমিকের পয়েন্টার charযা '\ 0' দিয়ে শেষ হয়।

range_errorপয়েন্টারটি বৈধ হতে পারে nullptrতবে এটি '\ 0' দিয়ে সমাপ্ত হলে এটি বৈধ হতে পারে না। সুতরাং এটি কোনও বৈধতা না করাই ভাল।

আমি স্ট্যান্ডার্ডে সঠিক শব্দটি জানি না, তবে এই প্রাক-শর্তটি সম্ভবত স্বয়ংক্রিয়ভাবে ধরে নেওয়া হয়েছে।


-2

এটি মৌলিক প্রশ্নে ফিরে যায় নালপ্ট্রার থেকে স্টাডি :: স্ট্রিং তৈরি করা কি ঠিক? এবং এটি কি করা উচিত?

www.cplusplus.com বলেছে

যদি s একটি নাল পয়েন্টার হয়, যদি n == npos হয়, বা [প্রথম, শেষ) দ্বারা নির্দিষ্ট রেঞ্জটি বৈধ নয়, এটি অনির্ধারিত আচরণের কারণ হয়।

তো কখন

throw std::range_error(nullptr);

বলা হয় বাস্তবায়ন এরকম কিছু করার চেষ্টা করে

store = std::make_shared<std::string>(nullptr);

যা অপরিজ্ঞাত। যা আমি একটি বাগ বিবেচনা করব (স্ট্যান্ডার্ডে আসল শব্দটি না পড়ে)। পরিবর্তে ল্যাবেরি বিকাশকারীরা এরকম কিছু তৈরি করতে পারত

if (what_arg)
  store = std::make_shared<std::string>(nullptr);

তবে তারপরে ক্যাচারকে নাল্প্টারের জন্য পরীক্ষা what();করতে হবে বা এটি কেবল সেখানেই ক্র্যাশ হয়ে যাবে। সুতরাং std::range_errorঅন্যটি কোনও ভাষার মতো একটি ফাঁকা স্ট্রিং বা "(নাল্প্টার)" নির্ধারণ করা উচিত।


"এটি আবার বেসিক প্রশ্নের দিকে ফিরে যায় নালপ্ট্রার থেকে স্টাডি :: স্ট্রিং তৈরি করা কি ঠিক?" - আমি মনে করি না এটা হয়।
কনরাড রুডল্ফ

আমি মনে করি না যে মানকটি কোথাও নির্দিষ্ট করে যে ব্যতিক্রমটি সংরক্ষণ করতে হবে std::stringএবং std::stringনির্মাণকারীকে ওভারলোড রেজোলিউশন দ্বারা চয়ন করা উচিত নয়।
আখরোট

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