রিলিজ বিল্ডস মধ্যে জোর দেওয়া উচিত


20

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

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

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

assert(ptr != nullptr);

যা বেশিরভাগ কোডে ছোট প্রভাব ফেলবে।

এটি আমাকে প্রশ্নের দিকে নিয়ে যায়: দাবিগুলি (ধারণাটির অর্থ, নির্দিষ্ট প্রয়োগ নয়) প্রকাশের ক্ষেত্রে সক্রিয় হওয়া উচিত? কেন না)?

দয়া করে নোট করুন যে এই প্রশ্নটি কীভাবে রিলিজ বিল্ডগুলিতে ( #undef _NDEBUGস্ব স্ব সংজ্ঞায়িত দৃ implementation় প্রয়োগের মতো বা ব্যবহারের ক্ষেত্রে) দৃ ser়তা সক্ষম করতে পারে তা নয় । তদ্ব্যতীত, এটি তৃতীয় পক্ষের / স্ট্যান্ডার্ড লাইব্রেরি কোডগুলিতে দাবিগুলি সক্ষম করার বিষয়ে নয় তবে আমার দ্বারা নিয়ন্ত্রিত কোডগুলিতে।


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

2
একটি পুরানো প্রবাদ আছে যে "দাবী সরিয়ে ফেলা কিছুটা বন্দরটিতে অনুশীলনের জন্য লাইফ-জ্যাকেট পরার মতো, তবে আপনার জাহাজ যখন উন্মুক্ত সমুদ্রের দিকে রওনা হয় তখন লাইফ-জ্যাকেটগুলি পেছনে ফেলে রেখে যায়" ( উইকি .২২.২০১৮ ) বিজ্ঞাপনগুলি অ্যাশ ডিফেন্সিয়াল প্রোগ্রামিং ) । আমি ব্যক্তিগতভাবে সেগুলি ডিফল্টরূপে রিলিজ বিল্ডগুলিতে সক্ষম করে রাখি। দুর্ভাগ্যক্রমে, এই অনুশীলনটি সি ++ বিশ্বে খুব বেশি প্রচলিত নয়, তবে কমপক্ষে খ্যাতিমান সি ++ প্রবীণ জেমস কানজে সর্বদা রিলিজের প্রতিশ্রুতি রাখার পক্ষে যুক্তি দিতেন: স্ট্যাকওভারফ্লো.com/a/ 12162195
ক্রিশ্চিয়ান হ্যাকেল

উত্তর:


20

ক্লাসিকটি assertপুরানো স্ট্যান্ডার্ড সি লাইব্রেরির একটি সরঞ্জাম, সি ++ থেকে নয়। এটি সি ++ তে এখনও অন্তত পিছনের সামঞ্জস্যের কারণে উপলব্ধ।

আমার হাতে সি স্ট্যান্ডার্ড লিবসের কোনও সঠিক টাইমলাইন নেই, তবে আমি নিশ্চিত যে assertকে অ্যান্ড আর সি লাইভে আসার পরে খুব শীঘ্রই উপলব্ধ ছিল (1978 সালের দিকে)। ক্লাসিক সিতে, শক্তিশালী প্রোগ্রামগুলি লেখার জন্য, এনএলএল পয়েন্টার পরীক্ষা এবং অ্যারের সীমা পরীক্ষা করা সি ++ এর চেয়ে বেশি ঘন ঘন সম্পন্ন করা দরকার। রেফারেন্স এবং / বা স্মার্ট পয়েন্টারগুলির পরিবর্তে পয়েন্টারগুলির সাহায্যে এবং NUL পয়েন্টার পরীক্ষাগুলির স্থূলতা এড়ানো যায় এবং ব্যবহার করে std::vectorঅ্যারে সীমা পরীক্ষা করা প্রায়শই অপ্রয়োজনীয়। তদুপরি, ১৯৮০-এ প্রদর্শিত পারফরম্যান্স অবশ্যই আজকের চেয়ে অনেক গুরুত্বপূর্ণ ছিল। সুতরাং আমি মনে করি সম্ভবত এটিই সম্ভবত ডিফল্টরূপে ডিবাগ বিল্ডগুলিতে সক্রিয় হওয়ার জন্য "দাবি" ডিজাইন করা হয়েছিল।

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

  • কিছু শর্ত পরীক্ষা করে (এবং শর্তটি ব্যর্থতার সুযোগে কার্যকর করা বন্ধ করে দেয়)

  • শর্তটি ধরে না রাখার ক্ষেত্রে একটি পরিষ্কার ত্রুটি বার্তা সরবরাহ করে

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

  • প্রতি কেস বেসের উপরের স্কোপটি সিদ্ধান্ত নিতে অনুমতি দেয় যে প্রোগ্রামটি সুদৃ .়ভাবে শেষ হওয়া উচিত, বা এটি চালিয়ে যেতে হবে কিনা।

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

যেহেতু ক্লাসিক assertএই বৈশিষ্ট্যগুলি সরবরাহ করে না, তাই এটি কোনও রিলিজ বিল্ডের জন্য উপযুক্ত নয়, ধরে নেওয়া হয়েছে যে রিলিজ বিল্ডটি কোনওটি প্রযোজনায় স্থাপন করে।

এখন আপনি জিজ্ঞাসা করতে পারেন যে কেন সি স্ট্যান্ডার্ড লাইবে এই ধরণের নমনীয়তা সরবরাহ করে এমন কোনও কার্যকারিতা বা প্রক্রিয়া নেই। আসলে, C ++, একটি মান যে পদ্ধতিতে এই সমস্ত বৈশিষ্ট্য (এবং আরও অনেক কিছু) আছে, এবং আপনি এটি জানেন: এটা বলা হয় ব্যতিক্রম

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


আহ, সি উত্তরাধিকার সম্পর্কে সম্পূর্ণরূপে ভুলে গেছি (তার সব পরে #include <cassert>)। এটি পুরোপুরি এখন উপলব্ধি করে।
কেউ

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

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

15

আপনি যদি নিজেকে খুঁজে পান এমন ইস্যুগুলি একটি রিলিজে সক্ষম হয়েছিল যা আপনি ভুল কাজটি করার অনুরোধ জানিয়েছেন।

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

যদি আপনার এমন কিছু মনে হয় যা রিলিজের সময়ও পরীক্ষা করা উচিত বলে মনে করেন তবে কোড লিখুন যা এটি পরীক্ষা করে। If throwকনস্ট্রাক্ট খুব ভাল কাজ করে। আপনি যদি অন্য ছোঁড়ার চেয়ে আলাদা কিছু বলতে চান তবে কেবল বর্ণনামূলক ব্যতিক্রম ব্যবহার করুন যা আপনি বলতে চান।

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

আমি দৃsert়তার একটি নির্দিষ্ট প্রয়োগের কথা বলছি না তবে একটি দৃ as়তার ধারণা। আমি দৃsert়তার অপব্যবহার বা পাঠকদের বিভ্রান্ত করতে চাই না। আমি বলতে চাইছিলাম কেন এটি প্রথম স্থানে রয়েছে। অতিরিক্ত রিলিজ_সেসার্ট কেন নেই? এর দরকার নেই? মুক্তির ক্ষেত্রে নিষ্ক্রিয় হওয়ার দাবি দেওয়ার পিছনে যুক্তি কী? - কেউ নেই

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

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

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


2
আমার অনুমান আমার প্রশ্ন: মুক্তির আগে এই কোডটি কেন সরানো হয়েছে? চেকগুলি কোনও পারফরম্যান্স ড্রেনের বেশি নয় এবং যদি তারা ব্যর্থ হয় তবে অবশ্যই একটি সমস্যা আছে যা আমি সম্পর্কে আরও সরাসরি ত্রুটির বার্তাটি পছন্দ করি। একটি দাবী পরিবর্তে একটি ব্যতিক্রম ব্যবহার করে আমার কী সুবিধা দেয়? আমি সম্ভবত catch(...)এটির সাথে সম্পর্কযুক্ত কোডটি সক্ষম হতে চাই না।
কেউ নেই

2
@ নোবডি অদম্য প্রয়োজনীয়তার জন্য দাবী না ব্যবহারের সবচেয়ে বড় সুবিধাটি আপনার পাঠকদের বিভ্রান্ত করা নয়। আপনি যদি কোডটি অক্ষম না করতে চান তবে এমন প্রতিমা ব্যবহার করবেন না যে এটি হবে signal এটি if (DEBUG)ডিবাগিং কোড ব্যতীত অন্য কিছু নিয়ন্ত্রণ করতে ব্যবহার করার মতোই খারাপ । মাইক্রো অপ্টিমাইজেশন আপনার ক্ষেত্রে কিছুই বোঝাতে পারে। তবে আপনার প্রয়োজনের প্রয়োজন না বলে প্রতিমাটি হস্তান্তর করা উচিত নয়।
candied_orange

আমি মনে করি আমি আমার অভিপ্রায়টি যথেষ্ট পরিস্কার করিনি। আমি একটি নির্দিষ্ট প্রয়োগের কথা বলছি না assertতবে একটি দৃ as়তার ধারণা। আমি assertপাঠকদের অপব্যবহার বা বিভ্রান্ত করতে চাই না । আমি বলতে চাইছিলাম কেন এটি প্রথম স্থানে রয়েছে। বাড়তি কিছু নেই কেন release_assert? এর দরকার নেই? মুক্তির ক্ষেত্রে নিষ্ক্রিয় হওয়ার দাবি দেওয়ার পিছনে যুক্তি কী?
কেউ নেই

2
You're asking for a good abstraction.আমি এটি সম্পর্কে নিশ্চিত নই। আমি মূলত এমন সমস্যাগুলি মোকাবিলা করতে চাই যেখানে কোনও পুনরুদ্ধার হয় না এবং এটি কখনই ঘটে না। এটি একসাথে নিয়ে যান Because production code needs to [...] not format the hard drive [...]এবং আমি যেসব মামলায় আক্রমণকারীদের ভেঙে ফেলা হয় সেগুলির জন্য বলব আমি যে কোনও সময় ইউবি-র মাধ্যমে মুক্তি চেয়েছি।
কেউ

1
@ নোবিডি "সমস্যাগুলি যেখানে পুনরুদ্ধার হয় না" তাদের ব্যতিক্রম ছুঁড়ে দিয়ে না ধরার মাধ্যমে মোকাবেলা করা যেতে পারে। আপনি লক্ষ করতে পারেন যে ব্যতিক্রমের বার্তা পাঠ্যে সেগুলি কখনও ঘটবে না।
candied_orange

4

প্রতিবেদনগুলি একটি ডিবাগিং সরঞ্জাম , কোনও ডিফেন্সিভ প্রোগ্রামিং কৌশল নয়। আপনি যদি সমস্ত পরিস্থিতিতে বৈধতা সম্পাদন করতে চান, তবে শর্তযুক্ত লিখে বৈধকরণ সম্পাদন করুন - বা বয়লারপ্লেট হ্রাস করার জন্য আপনার নিজের ম্যাক্রো তৈরি করুন।


4

assertডকুমেন্টেশনের একটি ফর্ম, মতামত মত। মতামত পছন্দ করুন, আপনি সাধারণত তাদের গ্রাহকদের কাছে প্রেরণ করবেন না - তারা প্রকাশের কোডে অন্তর্ভুক্ত নয়।

তবে মন্তব্যে সমস্যাটি হ'ল তারা পুরানো হয়ে যেতে পারে এবং তবুও তারা এগুলিতে চলে যায় That's এজন্য দৃser় প্রতিজ্ঞাগুলি ভাল - তারা ডিবাগ মোডে চেক করা হয়েছে। যখন দাবিটি অপ্রচলিত হয়ে যায়, আপনি দ্রুত এটিকে আবিষ্কার করবেন এবং এখনও কীভাবে এই দাবীটি ঠিক করবেন তা জানতে পারবেন। যে মন্তব্যটি 3 বছর আগে পুরানো হয়েছিল? কারও অনুমান।


1
কিছু খারাপ হওয়ার আগে কোনও ব্যর্থ আক্রমণকারীকে বাতিল করা কোনও বৈধ ব্যবহারের ক্ষেত্রে নয়?
কেউ

3

আপনি যদি কোনও "দৃsert়তা" বন্ধ না করতে চান, তবে একটি সাধারণ ক্রিয়া লিখতে নির্দ্বিধায় অনুরূপ প্রভাব রয়েছে:

void fail_if(bool b) {if(!b) std::abort();}

এটি হ'ল assertটেস্টগুলির জন্য যেখানে আপনি চান না যে তারা প্রেরিত পণ্যতে চলে যেতে পারে। আপনি যদি সেই পরীক্ষাটি প্রোগ্রামের সংজ্ঞায়িত আচরণের অংশ হতে চান assertতবে এটি ভুল সরঞ্জাম।


1
আমি এটি সম্পর্কে ভালভাবে অবগত। প্রশ্নটি কেন ডিফল্টরূপে এটির লাইনের পাশাপাশি রয়েছে।
কেউ

3

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

যে কোনও অপ্রত্যাশিত সমস্যার জন্য আপনাকে এটি নির্ধারণ করতে হবে যে বিকাশকারী এবং ব্যবহারকারী উভয়ের পক্ষে এটি পরিচালনা করার সর্বোত্তম উপায়।


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

এইচএম, verify(cond)ফলাফলটি দৃsert়ভাবে প্রকাশ করার এবং ফিরে পাওয়ার স্বাভাবিক উপায় হবে না ?
হস্তান্তরকারী

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

2

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

এটি স্থিতিশীল রিলিজ বিল্ডগুলি থেকে বাদ দেওয়ার জন্যও ডিজাইন করা হয়েছে , যে কোনও কারণেই বিকাশকারীরা কার্যকর মনে করতে পারেন: নন্দনতত্ব, পারফরম্যান্স, যা তারা চান। এটি কোনও ডিবাগ বিল্ডকে একটি রিলিজ বিল্ড থেকে আলাদা করে দেয় এমন একটি অংশ, এবং সংজ্ঞা অনুসারে একটি রিলিজ বিল্ড এ জাতীয় দাবি থেকে বঞ্চিত হয়। সুতরাং ডিজাইনের একটি বিপর্যয় আছে যদি আপনি অ্যানালজিকাল "রিলিজ বিল্ডটি প্লেস ইন দ্য অ্যাশারেন্সস " রিলিজ করতে চান যা একটি _DEBUGপ্রিপ্রোসেসর সংজ্ঞা এবং কোনও NDEBUGসংজ্ঞায়িত সহ একটি রিলিজ বিল্ডে চেষ্টা হবে ; এটি আসলে আর মুক্তি নয়।

নকশা এমনকি প্রমিত লাইব্রেরি পর্যন্ত প্রসারিত। অসংখ্য মধ্যে একটি খুব মৌলিক উদাহরণ হিসাবে, এর বাস্তবায়নের অনেকটা std::vector::operator[]হবে assertনিশ্চিত করুন যে আপনি সীমার বাইরে ভেক্টর চেক করছি না করতে একটি বৈধতা পরীক্ষা। আপনি যদি রিলিজ বিল্ডে এই জাতীয় চেক সক্ষম করে থাকেন তবে মানক গ্রন্থাগারটি অনেক বেশি কার্য সম্পাদন শুরু করবে start vectorব্যবহারের একটি মানদণ্ডoperator[]এবং একটি সরল পুরাতন গতিশীল অ্যারের বিপরীতে অন্তর্ভুক্ত এমন জালিয়াতিগুলির সাথে একটি ফিল ফিল্ড প্রায়শই গতিশীল অ্যারে দেখায় যে আপনি এই ধরনের চেকগুলি অক্ষম না করে যতক্ষণ না তারা প্রায়শই তুচ্ছ উপায় থেকে দূরে প্রভাব সম্পাদন করে। এখানে একটি নাল পয়েন্টার চেক এবং সীমানার বাইরে চেকগুলি আসলে একটি বিশাল ব্যয় হয়ে উঠতে পারে যদি এই ধরণের চেকগুলি স্মার্ট পয়েন্টারটিকে ডিফারেন্স করার বা অ্যারে অ্যাক্সেস করার মতো সহজ সরল কোডের পূর্ববর্তী কোডের প্রতিটি ফ্রেমে কয়েক মিলিয়নবার প্রয়োগ করা হয়।

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

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

মুক্তির আগে এই কোডটি কেন সরানো হয়েছে? চেকগুলি কোনও পারফরম্যান্স ড্রেনের বেশি নয় এবং যদি তারা ব্যর্থ হয় তবে অবশ্যই একটি সমস্যা আছে যা আমি সম্পর্কে আরও সরাসরি ত্রুটির বার্তাটি পছন্দ করি।

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

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

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

vector::at বনাম vector::operator[]

আমি মনে করি এই দুটি পদ্ধতির পার্থক্য এটির পাশাপাশি বিকল্প হিসাবেও রয়েছে: ব্যতিক্রম। সীমানার বাইরে কোনও ভেক্টর অ্যাক্সেস করার চেষ্টা করার সময় সীমা ছাড়িয়ে অ্যাক্সেস একটি সহজে-পুনরুত্পাদনযোগ্য ত্রুটি তৈরি করতে পারে তা নিশ্চিত করার জন্য vector::operator[]সাধারণত বাস্তবায়নগুলি assert। তবে গ্রন্থাগার প্রয়োগকারীরা এই ধারণাটি নিয়ে এটি করেন যে এটি একটি অনুকূলিতকরণের রিলিজ বিল্ডের জন্য কোনও অর্থ ব্যয় করবে না।

ইতিমধ্যে vector::atপ্রদান করা হয় যা সর্বদা সীমার বাইরে চলে না এমনকি রিলিজ বিল্ডগুলিতে ছুঁড়ে ফেলে তবে এটিতে এর একটি কার্যক্ষমতা পেনাল্টি রয়েছে যেখানে আমি প্রায়শই এর vector::operator[]চেয়ে বেশি কোড ব্যবহার করে দেখি vector::at। সি ++ এর অনেকগুলি নকশায় "আপনি যা ব্যবহার করেন / যা প্রয়োজন তার জন্য অর্থ প্রদান করুন" ধারণাটি প্রতিধ্বনিত করে এবং প্রচুর লোকেরা প্রায়শই অনুগ্রহ করে operator[], যা তারা প্রকাশ না করে এমন ধারণার উপর ভিত্তি করে রিলিজ বিল্ডিংয়ের সীমানা পরীক্ষা করেও বিরক্ত করে না তাদের অনুকূলিতকরণের রিলিজ বিল্ডগুলিতে সীমা পরীক্ষা করার দরকার নেই। হঠাৎ যদি দাবিগুলি রিলিজ বিল্ডগুলিতে সক্ষম হয়, তবে এই দুটির পারফরম্যান্স অভিন্ন হবে এবং ভেক্টরের ব্যবহার সর্বদা গতিশীল অ্যারের চেয়ে ধীর হয়ে যায়। সুতরাং দৃser়বিজ্ঞানের নকশা এবং সুবিধার একটি বিশাল অংশ এই ধারণার উপর ভিত্তি করে যে তারা একটি মুক্তির বিল্ডে মুক্ত হয় free

release_assert

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

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

আসলে কিছু ক্ষেত্রে রয়েছে যেখানে আমি একটি লাইন নম্বর এবং ত্রুটি বার্তা সহ কৃপণভাবে একটি নিক্ষিপ্ত ব্যতিক্রম থেকে ভালভাবে পুনরুদ্ধার করাকে পছন্দ করব যা একটি রিলিজ রাখতে যথেষ্ট সস্তা হতে পারে। এবং এমন কিছু মামলা রয়েছে যেখানে কোনও ব্যতিক্রম থেকে পুনরুদ্ধার করা অসম্ভব যেমন একটি বিদ্যমান পরিস্থিতি থেকে পুনরুদ্ধার করার চেষ্টা করার সময় একটি ত্রুটি হয়েছিল। সেখানে আমি একটি জন্য উপযুক্ত উপযুক্ত খুঁজে release_assert(!"This should never, ever happen! The software failed to fail!");পেয়েছিলাম এবং স্বাভাবিকভাবেই এটি ময়লা সস্তা যেহেতু চেকটি প্রথমে একটি ব্যতিক্রমী পথের অভ্যন্তরে সঞ্চালিত হবে এবং সাধারণ সম্পাদনের পথে কোনও ব্যয় হবে না।


আমার উদ্দেশ্যটি তৃতীয় পক্ষের কোডটিতে দৃser়তা সক্ষম করার ছিল না, স্পষ্টকরণ সম্পাদনা দেখুন। আমার মন্তব্যের উদ্ধৃতিটি আমার প্রশ্ন থেকে প্রসঙ্গটি বাদ দেয়: Additionally, the performance argument for me only counts when it is a measurable problem.সুতরাং মুক্তিটি থেকে বেরিয়ে আসার জন্য কখন একটি দৃser়তার বিষয়ে সিদ্ধান্ত নেওয়ার বিষয়টি কেস ভিত্তিতে সিদ্ধান্ত নেওয়ার ধারণা।
কেউ নেই

সর্বশেষ মন্তব্যে অন্যতম সমস্যা হ'ল স্ট্যান্ডার্ড লাইব্রেরি একই ব্যবহার করে assertযা _DEBUG/NDEBUGআপনি assertম্যাক্রো ব্যবহার করার সময় আপনি কী ব্যবহার করবেন সেই একই প্রিপ্রোসেসর ডিফের উপর নির্ভর করে । সুতরাং স্ট্যান্ডার্ড লিবের জন্য এটি সক্ষম না করে কেবল এক টুকরো কোডের জন্য বাছাই করে নির্বাচনের পক্ষে কোনও উপায় নেই, উদাহরণস্বরূপ, ধরে নেওয়া যে এটি স্ট্যান্ডার্ড লিব ব্যবহার করে।

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

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

vector::operator[]এবং vector::at, উদাহরণস্বরূপ, রিলিজ বিল্ডগুলিতে operator[]দৃ as়তাগুলি সক্ষম করা থাকলে কার্যত একই পারফরম্যান্সটি ঘটতে পারে এবং পারফরম্যান্সের দিক থেকে এটি আর ব্যবহার করার কোনও অর্থ হয় না যেহেতু এটি যেভাবেই সীমাবদ্ধতা পরীক্ষা করতে চাইবে।

2

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

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

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