সি ++ স্ট্যান্ডার্ড কি একটি প্রোগ্রাম ক্র্যাশ করার জন্য একটি অনির্দেশিত পুলকে মঞ্জুরি দেয়?


500

আমি জানি যে সি ++ তে একটি "অপরিজ্ঞাত আচরণ" সংকলকটিকে যে কোনও কিছু করতে দেওয়ার অনুমতি দিতে পারে। তবে, আমি একটি ক্র্যাশ পেয়েছিলাম যা আমাকে অবাক করেছিল, কারণ আমি ধরে নিয়েছিলাম যে কোডটি যথেষ্ট নিরাপদ।

এই ক্ষেত্রে, আসল সমস্যাটি কেবলমাত্র নির্দিষ্ট সংকলক ব্যবহার করে নির্দিষ্ট প্ল্যাটফর্মে ঘটেছিল এবং কেবলমাত্র অপটিমাইজেশন সক্ষম করা থাকলে।

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

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

// Zero-filled global buffer of 16 characters
char destBuffer[16];

void Serialize(bool boolValue) {
    // Determine which string to print based on boolValue
    const char* whichString = boolValue ? "true" : "false";

    // Compute the length of the string we selected
    const size_t len = strlen(whichString);

    // Copy string into destination buffer, which is zero-filled (thus already null-terminated)
    memcpy(destBuffer, whichString, len);
}

এই কোডটি ঝাঁকুনি 5.0.0 + অপ্টিমাইজেশনের মাধ্যমে কার্যকর করা হলে এটি ক্র্যাশ / ক্যান করতে পারে।

প্রত্যাশিত টার্নারি-অপারেটরটি boolValue ? "true" : "false"আমার পক্ষে যথেষ্ট নিরাপদ বলে মনে হয়েছিল, আমি ধরেই নিয়েছিলাম, "আবর্জনার মূল্য যা কিছু হোক boolValueনা কেন, এটি যেহেতু সত্য বা মিথ্যা মূল্যায়ন করবে।"

আমার কাছে একটি কম্পাইলার এক্সপ্লোরার উদাহরণ সেটআপ আছে যা ডিসমাসে সমস্যা দেখায়, এখানে সম্পূর্ণ উদাহরণ। দ্রষ্টব্য: সমস্যাটিকে তিরস্কার করার জন্য, আমি যে সংমিশ্রণটি পেয়েছি তা হ'ল -O2 অপ্টিমাইজেশানের সাথে ঝাঁকুনি 5.0.0 ব্যবহার করে।

#include <iostream>
#include <cstring>

// Simple struct, with an empty constructor that doesn't initialize anything
struct FStruct {
    bool uninitializedBool;

   __attribute__ ((noinline))  // Note: the constructor must be declared noinline to trigger the problem
   FStruct() {};
};

char destBuffer[16];

// Small utility function that allocates and returns a string "true" or "false" depending on the value of the parameter
void Serialize(bool boolValue) {
    // Determine which string to print depending if 'boolValue' is evaluated as true or false
    const char* whichString = boolValue ? "true" : "false";

    // Compute the length of the string we selected
    size_t len = strlen(whichString);

    memcpy(destBuffer, whichString, len);
}

int main()
{
    // Locally construct an instance of our struct here on the stack. The bool member uninitializedBool is uninitialized.
    FStruct structInstance;

    // Output "true" or "false" to stdout
    Serialize(structInstance.uninitializedBool);
    return 0;
}

অপ্টিমাইজারের কারণে সমস্যা দেখা দেয়: "সত্য" এবং "মিথ্যা" স্ট্রিংগুলি কেবল দৈর্ঘ্যে 1 দ্বারা পৃথক হয় তা অনুমান করার পক্ষে যথেষ্ট চালাক ছিল So সুতরাং প্রকৃত দৈর্ঘ্য গণনা করার পরিবর্তে এটি নিজেই বুলের মান ব্যবহার করে, যা উচিত প্রযুক্তিগতভাবে 0 বা 1 হয়, এবং এর মতো হয়:

const size_t len = strlen(whichString); // original code
const size_t len = 5 - boolValue;       // clang clever optimization

যদিও এটি "চালাক", তাই বলার জন্য, আমার প্রশ্নটি: সি ++ স্ট্যান্ডার্ডের দ্বারা কি একটি সংকলককে একটি বুল অনুমান করতে দেয় যে কেবল '0' বা '1' এর অভ্যন্তরীণ সংখ্যাগত উপস্থাপনা থাকতে পারে এবং এটিকে এভাবে ব্যবহার করা যায়?

অথবা এটি বাস্তবায়ন-সংজ্ঞায়নের ক্ষেত্রে, সেই ক্ষেত্রে বাস্তবায়নটি ধরে নিয়েছে যে এর সমস্ত গুলিতে কেবল কখনও 0 বা 1 থাকবে এবং অন্য কোনও মান অপরিবর্তিত আচরণের অঞ্চল?


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

7
লক্ষ্য করুন যে true"বুলিয়ানকে অ্যাসাইনমেন্ট" সহ যা বুলিয়ান অপারেশন সম্পর্কে "অ-শূন্যকে মূল্যায়ন করে " এর প্রয়োজনীয়তা (যা static_cast<bool>()স্পষ্টভাবে নির্দিষ্টকরণের উপর নির্ভর করে অনুরোধ করতে পারে ) একটি নিয়ম। boolসংকলক দ্বারা নির্বাচিত কোনও অভ্যন্তরীণ উপস্থাপনা সম্পর্কে এটি অবশ্য প্রয়োজনীয় নয় ।
ইউরো মিশেল্লি

2
মন্তব্যগুলি বর্ধিত আলোচনার জন্য নয়; এই কথোপকথন চ্যাটে সরানো হয়েছে ।
স্যামুয়েল লিউ

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

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

উত্তর:


285

হ্যাঁ, আইএসও সি ++ এই পছন্দটি করার জন্য বাস্তবায়নের অনুমতি দেয় (তবে প্রয়োজন হয় না)।

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

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


আপনি x86-64 সিস্টেম ভি এবিআইয়ের জন্য সংকলন করছেন , যা উল্লেখ করে যে boolকোনও রেজিস্টারে ফাংশন আর্গ হিসাবে বিট-প্যাটার্নগুলি false=0এবংtrue=1 নিবন্ধের 1 এর কম 8 বিটগুলিতে প্রতিনিধিত্ব করা হয় । মেমোরিতে, boolএকটি 1-বাইট প্রকার যা আবার 0 বা 1 এর পূর্ণসংখ্যার মান হওয়া আবশ্যক।

(একটি এবিআই বাস্তবায়ন পছন্দগুলির একটি সেট যা একই প্ল্যাটফর্মের সংকলকরা এতে একমত হয় যাতে তারা কোড তৈরি করতে পারে যা একে অপরের ফাংশনগুলিতে কল করে, টাইপ আকার, কাঠামোর বিন্যাস বিধিবদ্ধকরণ এবং কলিং কনভেনশন সহ including)

আইএসও সি ++ এটি নির্দিষ্ট করে না, তবে এবিআইয়ের এই সিদ্ধান্তটি ব্যাপক কারণ এটি বুল-> ইন রূপান্তরকে সস্তা করে তোলে (কেবল শূন্য-এক্সটেনশন) । আমি এমন কোনও এবিআই সম্পর্কে অবগত নই যা boolকোনও আর্কিটেকচারের জন্য (কেবল x86 নয়) সংকলককে 0 বা 1 ধরে নিতে দেয় না। মনে হচ্ছে অপ্টিমাইজেশন পারবেন !myboolসঙ্গে xor eax,1: কম বিট টুসকি কোন সম্ভাব্য কোডটি 0 এবং 1 এর মধ্যে একটি বিট / পূর্ণসংখ্যা / bool, টুসকি করতে একক CPU- র নির্দেশনা । বা প্রকারের a&&bজন্য এবং কিছুটা দিকের সংকলন bool। কিছু সংকলক আসলে 8 বিট হিসাবে সংকলক হিসাবে বুলিয়ান মান গ্রহণ করে তাদের উপর অপারেশন কি অকার্যকর?

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

সংকলকটি অবশ্যই তার কোড-জেনে কোনও এবিআই গ্যারান্টির পুরো সুবিধা নেওয়ার অনুমতি পেয়েছে এবং আপনার মতো কোড তৈরি করতে strlen(whichString)পারে যা কোনটি উপযুক্ত করে
5U - boolValue
(বিটিডাব্লু, এই অপ্টিমাইজেশনটি ধূর্ত চালাক, তবে সম্ভবত সংক্ষিপ্ততর বনাম ব্রাঞ্চিং এবং memcpyতাত্ক্ষণিক ডেটা 2 হিসাবে স্টোর হিসাবে অন্তর্নিহিত ))

অথবা সংকলকটি পয়েন্টারগুলির একটি সারণী তৈরি করতে পারে এবং boolআবার এটি 0 বা 1 বলে ধরে নিয়ে এর পূর্ণসংখ্যার মান সহ সূচী তৈরি করতে পারে (( বারমারের উত্তর প্রস্তাবিত এই সম্ভাবনাটিই তাই ))


__attribute((noinline))অপ্টিমাইজেশান সক্ষম আপনার নির্মাণকারীর ঝাঁকুনির কারণ হিসাবে স্ট্যাক থেকে কেবল একটি বাইট লোড করা হয়েছিল uninitializedBool। এটা তোলে বস্তুর জন্য স্থান তৈরি mainসঙ্গে push rax(যা ক্ষুদ্রতর এবং বিভিন্ন কারণে হিসাবে দক্ষ হিসাবে সম্পর্কে sub rsp, 8), তাই যাই হোক না কেন আবর্জনা এন্ট্রি উপর আওয়ামী লীগের যে অবস্থায় ছিল সেই mainমান জন্য ব্যবহার করা হয় uninitializedBool। এ কারণেই আপনি আসলে এমন মান পেয়েছেন যা কেবল ছিল না 0

5U - random garbageআনম্যাপযুক্ত মেমরিতে যেতে মেমকিটিকে নেতৃত্ব দিয়ে সহজেই একটি বৃহত স্বাক্ষরিত মানকে মোড়তে পারে। গন্তব্য স্থিতিশীল স্টোরেজে রয়েছে, স্ট্যাক নয়, সুতরাং আপনি কোনও ফেরতের ঠিকানা বা অন্য কোনও বিষয়কে ওভাররাইট করছেন না।


অন্যান্য বাস্তবায়নগুলি বিভিন্ন পছন্দ করতে পারে, যেমন false=0এবং true=any non-zero value। তারপরে ঝাঁকুনি সম্ভবত ইউবি- র এই নির্দিষ্ট উদাহরণের জন্য ক্র্যাশ করা কোড তৈরি করবে না । (তবে এটি চাইলে এটি অনুমতি দেওয়া হবে)) x86-64 এর জন্য অন্য কিছু বেছে নেওয়া এমন কোনও বাস্তবায়ন আমার জানা নেই bool, তবে সি ++ স্ট্যান্ডার্ড এমন অনেক কিছুই মঞ্জুরি দেয় যা কেউ করে না বা এমনকি এটি করতে চায় না হার্ডওয়্যার যা বর্তমানের সিপিইউগুলির মতো কিছু।

আইএসও সি ++ এটিকে কোনও অজানা প্রতিনিধিত্ব পরীক্ষা করে বা সংশোধন করার সময় আপনি কী পাবেন তা অনির্দিষ্ট করে ছেড়ে দেয়bool । (যেমন দ্বারা memcpying boolমধ্যে unsigned char, যা আপনি কারণ করার অনুমতি করছি char*করতে পারেন ওরফে কিছু। এবং unsigned charকোনো প্যাডিং বিট আছে নিশ্চিত করা হয়, তাই C ++ স্ট্যান্ডার্ডের আনুষ্ঠানিকভাবে যদি আপনি কোন UB ছাড়া বস্তুর উপস্থাপনা hexdump দিন নেই। বস্তুর অনুলিপি করতে পয়েন্টার ভোটদান প্রতিনিধিত্ব নির্ধারণের চেয়ে আলাদা char foo = my_bool, অবশ্যই, তাই 0 বা 1 তে বুলিওনাইজেশন ঘটবে না এবং আপনি কাঁচা বস্তুর প্রতিনিধিত্ব পাবেন))

আপনি থাকেন আংশিকভাবে "লুকানো" সঙ্গে কম্পাইলার থেকে এই সঞ্চালনের পথে UBnoinline । এমনকি যদি এটি ইনলাইন না করে তবে ইন্টারপ্রেসিডুরাল অপটিমাইজেশনগুলি এখনও ফাংশনের একটি সংস্করণ তৈরি করতে পারে যা অন্য ফাংশনের সংজ্ঞা উপর নির্ভর করে। (প্রথমত, ঝাঁকুনি একটি এক্সিকিউটেবল তৈরি করছে, ইউনিক্স শেয়ার্ড লাইব্রেরি নয়, যেখানে প্রতীক-ইন্টারপজেশন ঘটতে পারে। দ্বিতীয়ত, সংজ্ঞাটির অভ্যন্তরে class{}সংজ্ঞা তাই সমস্ত অনুবাদ ইউনিটগুলির অবশ্যই একই সংজ্ঞা থাকতে হবে। inlineকীওয়ার্ডের মতো ।)

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

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

জিসিসি ও অনুশীলন মধ্যে ঝনঝন শব্দ না আসলে কখনও কখনও নির্গত ud2পরিবর্তে এমনকি মৃত্যুদণ্ড পাথ কোনো অর্থে দেখা যায় কোড জেনারেট করতে চেষ্টা, UB উপর। বা কোনও অ- voidকার্যকারিতা শেষে পড়ে যাওয়ার মতো ক্ষেত্রে , কখনও কখনও জিসিসি কোনও retনির্দেশ বাদ দেয় । আপনি যদি ভাবছিলেন যে "আমার ফাংশনটি RAX এ যা কিছু আবর্জনা রয়েছে তা দিয়েই ফিরে আসবে", আপনি খুব খারাপভাবে ভুল হয়ে গেছেন। আধুনিক সি ++ সংকলকরা আর কোনও পোর্টেবল সমাবেশের ভাষার মতো ভাষা ব্যবহার করে না। আপনার কার্যকারিতাটির অবিচ্ছিন্ন অ-ইনলাইনড সংস্করণটি কীভাবে asm এ দেখা যাবে সে সম্পর্কে অনুমান করা ছাড়াই আপনার প্রোগ্রামটি সত্যই বৈধ সি ++ হতে হবে।

আর একটি মজাদার উদাহরণ হ'ল এমএমপিড মেমরিটিতে স্বাক্ষরবিহীন অ্যাক্সেসটি কেন কখনও কখনও এএমডি 64 এ সেগফল্ট করে? । x86 আন-স্বাক্ষরিত পূর্ণসংখ্যার উপর দোষ দেয় না, তাই না? তাহলে কেন ভুল পথে চালিত uint16_t*সমস্যা হবে? কারণ alignof(uint16_t) == 2, এবং এই অনুমানের লঙ্ঘন করলে এসএসই 2-এর সাথে স্বয়ংক্রিয়ভাবে ভেক্টরাইজ করার সময় সেগফল্টের দিকে নিয়ে যায়।

আরও দেখুন কি প্রতিটি সি প্রোগ্রামার উচিত জানা অনির্ধারিত আচরণ # 1/3 সম্বন্ধে , একটি ঝনঝন ডেভেলপার দ্বারা একটি নিবন্ধ।

কী পয়েন্ট: যদি কম্পাইলার কম্পাইল সময়ে UB খেয়াল, এটা পারে "বিরতি" আপনার কোড মাধ্যমে (বিস্ময়কর এ এস এম নির্গত) পথ যা কারণ এমনকি একটি ABI- র যেখানে কোনো বিট-প্যাটার্ন জন্য একটি বৈধ বস্তু উপস্থাপনা লক্ষ্য করে যদি UB bool

প্রোগ্রামার দ্বারা অনেক ভুলের প্রতি সম্পূর্ণ শত্রুতা প্রত্যাশা করুন, বিশেষত আধুনিক সংকলকরা যে বিষয়গুলি সম্পর্কে সতর্ক করে দিয়েছে। এজন্য আপনার -Wallসতর্কতা ব্যবহার করা এবং ঠিক করা উচিত । সি ++ কোনও ব্যবহারকারী-বান্ধব ভাষা নয় এবং সি ++ এর কিছু এমন কিছু ক্ষেত্রেও অনিরাপদ হতে পারে যদিও আপনি যে টার্গেটটি সংকলন করছেন তার পক্ষে এটি নিরাপদে থাকবে। (উদাহরণস্বরূপ স্বাক্ষরিত ওভারফ্লো সি ++ এ ইউবি এবং সংকলকরা ধরে নেবে যে 2 এর পরিপূরক x86 এর জন্য সংকলন করার পরেও, আপনি ব্যবহার না করেই clang/gcc -fwrapv।)

সংকলন-সময়-দৃশ্যমান ইউবি সর্বদা বিপজ্জনক, এবং এটি নিশ্চিত হওয়া সত্যিই কঠিন (লিঙ্ক-টাইম অপ্টিমাইজেশান সহ) যে আপনি সত্যিই সংকলকটি থেকে ইউবি লুকিয়ে রেখেছেন এবং এটি কী ধরণের এএসএম তৈরি করবে সে সম্পর্কে যুক্তিযুক্ত হতে পারে।

অতিরিক্ত নাটকীয় হতে হবে না; প্রায়শই সংকলকগুলি আপনাকে কিছু জিনিস দিয়ে দূরে সরে যায় এবং কোডটি এমিটের মতো সারণী করে দেয় যা আপনি যখন কিছুটা ইউবি হয় তখনও আপনি প্রত্যাশা করেন। তবে ভবিষ্যতে সমস্যা হতে পারে যদি সংকলক কিছু অপ্টিমাইজেশন প্রয়োগ করে যা মান-সীমা সম্পর্কে আরও তথ্য অর্জন করে (যেমন একটি পরিবর্তনশীল অ-নেতিবাচক, সম্ভবত এটি x86- এ শূন্য-এক্সটেনশন মুক্ত সাইন-এক্সটেনশনটিকে অনুকূলিতকরণের অনুমতি দেয়) 64)। উদাহরণস্বরূপ, বর্তমান জিসিসি এবং বিড়ম্বনায়, করা সর্বদা-মিথ্যা হিসাবে tmp = a+INT_MINঅনুকূলিত হয় না a<0, কেবল এটি tmpসর্বদা নেতিবাচক। (কারণ INT_MIN+ a=INT_MAXএই 2 এর পরিপূরক টার্গেটের জন্য নেতিবাচক, এবং এর aচেয়ে বড় কোনওটি হতে পারে না))

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

এছাড়াও নোট করুন যে বাস্তবায়নগুলি (ওরফে সংকলক) এমন আচরণের সংজ্ঞা দিতে মঞ্জুরি দেয় যা আইএসও সি ++ অপরিবর্তিত থাকে । উদাহরণ হিসেবে বলা যায়, সব কম্পাইলার যে সমর্থন ইন্টেলের intrinsics (যেমন _mm_add_ps(__m128, __m128)ম্যানুয়াল SIMD vectorization জন্য) বিরচন ভুল প্রান্তিককৃত পয়েন্টার, যা সি মধ্যে UB হয় ++, এমনকি যদি আপনি অনুমতি প্রদান করা আবশ্যক না তাদের ডি-রেফারেন্স। __m128i _mm_loadu_si128(const __m128i *)বিভ্রান্তিকর __m128i*আর্গুমেন্ট গ্রহণ করে স্বাক্ষরবিহীন লোডগুলি করে , একটি void*বা নয় char*হার্ডওয়্যার ভেক্টর পয়েন্টার এবং সংশ্লিষ্ট ধরণের মধ্যে `পুনরায় ব্যাখ্যা_কাস্টিং কি একটি অপরিজ্ঞাত আচরণ?

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

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


পাদটীকা 1 : উপরের 56 টি বিট আবর্জনা হতে পারে যা কলিকে অবশ্যই উপেক্ষা করতে হবে, যেমন নিবন্ধের চেয়ে সংকীর্ণ প্রকারের জন্য usual

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

উদাহরণস্বরূপ, কল করার আগে কলকারী a & 0x01010101আরডিআইতে গণনা করেছেন এবং এটি অন্য কোনও কিছুর জন্য ব্যবহার করেছেন bool_func(a&1)। কলার অপ্টিমাইজ করতে পারে &1কারণ এটি ইতিমধ্যে এর অংশ হিসাবে লো বাইটে and edi, 0x01010101এটি করেছিল এবং এটি জানে যে উচ্চ বাইটগুলি উপেক্ষা করার জন্য কলি প্রয়োজন।

অথবা যদি কোনও তৃতীয় তর্ক হিসাবে পাস হয়, তবে কোড-সাইজের জন্য অনুকূল একটি কলকারী mov dl, [mem]তার পরিবর্তে লোড করে movzx edx, [mem], আরডিএক্সের পুরানো মান (বা অন্যান্য আংশিক-নিবন্ধের প্রভাবের উপর নির্ভর করে, একটি মিথ্যা নির্ভরতার দামে 1 বাইট সঞ্চয় করে) সিপিইউ মডেলটিতে)। বা mov dil, byte [r10]পরিবর্তে প্রথম তর্কটির জন্য movzx edi, byte [r10], কারণ উভয়ই যাইহোক RX উপসর্গের প্রয়োজন।

এই কেন ঝনঝন নিঃসরণ করে হয় movzx eax, dilযে Serializeপরিবর্তে sub eax, edi। (পূর্ণসংখ্যার উপাখ্যানগুলির জন্য, ক্ল্যাং জিসি-র শিরোনামহীন আচরণের উপর নির্ভর করে শূন্য- অথবা সাইন-প্রসারিত সরু পূর্ণসংখ্যার 32 বিটের উপর নির্ভর করে a২ বিট অফসেটের জন্য পয়েন্টারে সংযুক্ত করার সময় একটি চিহ্ন বা শূন্য এক্সটেনশন প্রয়োজন কি? x86-64 এবিআই? সুতরাং আমি আগ্রহী যে এটি একই জিনিসটি না করে তা দেখতে আগ্রহী bool))


পাদটীকা 2: শাখার পরে, আপনি কেবল একটি 4 বাইট- movমিমিটেড, বা একটি 4 বাইট + 1-বাইট স্টোর পাবেন। দৈর্ঘ্য স্টোর প্রস্থ + অফসেটগুলিতে অন্তর্ভুক্ত।

ওটিওএইচ, গ্লিবিসি মেম্পপি দৈর্ঘ্যের উপর নির্ভর করে একটি ওভারল্যাপ সহ দুটি 4-বাইট লোড / স্টোর করবে so সুতরাং এটি সত্যিই পুরো জিনিসটি বুলিয়ানের শর্তাধীন শাখাগুলি মুক্ত করে। গ্লিবসি'র মেমকি / মেমোমোভের L(between_4_7):ব্লকটি দেখুন । বা কমপক্ষে, মেমকপির ব্রাঞ্চিংয়ে বুলিয়ান উভয়ের জন্য একই আকারে একটি খণ্ড আকার নির্বাচন করুন।

যদি movইনলাইন করা থাকে তবে আপনি 2x -সিমিয়েড + cmovএবং শর্তসাপেক্ষ অফসেট ব্যবহার করতে পারেন বা স্ট্রিং ডেটা মেমরিতে রেখে দিতে পারেন।

অথবা যদি ইন্টেল আইস লেকের জন্য টিউন করা হয় ( ফাস্ট শর্ট আরইপি এমওভি বৈশিষ্ট্য সহ ), প্রকৃত পক্ষে সর্বোত্তম rep movsbহতে পারে। glibc সেই বৈশিষ্ট্য সহ CPU- তে ছোট আকারের জন্য memcpyব্যবহার শুরু করতে পারে rep movsb, যা অনেকগুলি ব্রাঞ্চিংয়ের সঞ্চয় করে।


ইউবি সনাক্তকরণ এবং অনিবার্য মানগুলির ব্যবহারের সরঞ্জাম

জিসিসি এবং ক্ল্যাং-এ আপনি -fsanitize=undefinedরান-টাইম উপকরণ যুক্ত করতে সংকলন করতে পারেন যা রানটাইম সময়ে ঘটে যাওয়া ইউবিতে সতর্কতা বা ত্রুটি ঘটবে। যদিও এটি এককীকরণযুক্ত ভেরিয়েবলগুলি ধরবে না। (কারণ এটি "অবিচ্ছিন্ন" বিটের জন্য জায়গা তৈরি করতে ধরণের আকারকে বাড়ায় না))

Https://developers.redhat.com/blog/2014/10/16/gcc-undefined-behavior-sanitizer-ubsan/ দেখুন

অবিচ্ছিন্ন তথ্য ব্যবহারের জন্য, ঝড় / এলএলভিএম-এ অ্যাড্রেস স্যানিটাইজার এবং মেমরি স্যানিটাইজার রয়েছে। https://github.com / clang -fsanitize=memory -fPIE -pieগুগল / স্যানিটাইজারস / উইকি / মেমরিস্যানিটাইজার অবিরাম মেমরি পড়ার সনাক্তকরণের উদাহরণগুলি দেখায় । আপনি অপ্টিমাইজেশন ছাড়াই সংকলন করতে পারলে এটি সর্বোত্তমভাবে কাজ করতে পারে , সুতরাং ভেরিয়েবলগুলির সমস্ত পাঠ শেষ পর্যন্ত এসেমের মেমরি থেকে লোড হয়। তারা দেখায় যে এটি এমন -O2কোনও ক্ষেত্রে ব্যবহৃত হচ্ছে যেখানে লোডটি অপ্টিমাইজ হবে না। আমি নিজে চেষ্টা করে দেখিনি। (কিছু ক্ষেত্রে, উদাহরণস্বরূপ কোনও অ্যারে যোগ করার আগে কোনও সংযোজককে সূচনা না করা, ঝনঝন -O3 এমন কোনও ভেক্টর রেজিস্টারে যে কোডটি আরম্ভ হয় নি তার প্রেরণ করবে So সুতরাং অপ্টিমাইজেশনের মাধ্যমে, আপনার ক্ষেত্রে এমন একটি ঘটনা ঘটতে পারে যেখানে ইউবির সাথে কোনও স্মৃতি পড়েনি memory .কিন্তু-fsanitize=memory উত্পাদিত asm পরিবর্তন করে এবং এর জন্য একটি চেকের ফলাফল হতে পারে))

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

মেমরিস্যানিটাইজার ভালগ্রিড (মেমচেক সরঞ্জাম) এ পাওয়া কার্যকারিতার একটি উপসেট প্রয়োগ করে।

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

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

সম্ভবত কেবল একটি লোডকে পতাকাঙ্কিত না করার পিছনে ধারণাটি হ'ল স্ট্রাক্টগুলিতে প্যাডিং থাকতে পারে এবং পৃথক সদস্যরা কেবল একবারে একটি করে লেখা থাকলেও পুরো স্ট্রাক্টকে (প্যাডিং সহ) প্রশস্ত ভেক্টর লোড / স্টোর দিয়ে অনুলিপি করা কোনও ত্রুটি নয়। এএসএম স্তরে, কী প্যাডিং ছিল এবং আসলে মূল্যের একটি অংশ কী ছিল তার তথ্য হারিয়ে গেছে।


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

2
@ জোশুয়া: ওহ ঠিক আছে, ভাল কথা, ইটানিয়ামের স্পষ্ট অনুমানগুলি "সংখ্যার নয়" এর সমতুল্য মূল্যবোধকে ট্যাগ করবে যেমন মান ত্রুটিগুলি ব্যবহার করে।
পিটার কর্ডেস

11
তদ্ব্যতীত , এটিও ব্যাখ্যা করে যে কেন ইউবি ফিচারব্যাগটি প্রথমে সি এবং সি ++ ভাষাগুলির নকশায় প্রবর্তিত হয়েছিল: কারণ এটি সংকলককে ঠিক এই ধরণের স্বাধীনতা দেয়, যা এখন সবচেয়ে আধুনিক সংকলককে এই উচ্চ-মানের সম্পাদনের অনুমতি দিয়েছে which অপ্টিমাইজেশন যা সি / সি ++ এমন উচ্চ-কার্য সম্পাদনের মধ্য-স্তরের ভাষা করে।
The_Sympathizer

2
এবং তাই সি ++ সংকলক লেখক এবং সি ++ প্রোগ্রামারদের মধ্যে দরকারী প্রোগ্রাম লেখার চেষ্টা করার মধ্যে যুদ্ধ অব্যাহত রয়েছে। এই প্রশ্নের উত্তর দেওয়ার ক্ষেত্রে সম্পূর্ণ বিস্তৃত এই উত্তরটি স্থির বিশ্লেষণ সরঞ্জামগুলির বিক্রেতাদের জন্য
দৃ ad়প্রত্যয়ী

4
@ দ্য সিম্পাথাইজার: তাদের গ্রাহকদের পক্ষে যে উপায়ে সবচেয়ে কার্যকর হবে তা যে কোনও উপায়ে বাস্তবায়নের অনুমতি দেওয়ার জন্য ইউবি অন্তর্ভুক্ত ছিল । সমস্ত আচরণকে সমানভাবে কার্যকর হিসাবে বিবেচনা করা উচিত এমন পরামর্শ দেওয়ার উদ্দেশ্য ছিল না।
সুপারক্যাট

56

সংকলকটিকে ধরে নিতে অনুমান করা হয় যে আর্গুমেন্ট হিসাবে পাস করা একটি বুলিয়ান মান একটি বৈধ বুলিয়ান মান (অর্থাত্ একটি যা প্রাথমিক বা রূপান্তরিত হয়েছে trueবা false)। trueপ্রকৃতপক্ষে সেখানে বিভিন্ন উপস্থাপনা হতে পারে - মান পূর্ণসংখ্যা 1 একই হতে হবে তা নয় trueএবং false- কিন্তু প্যারামিটার ঐ দুই মূল্যবোধ, যেখানে "বৈধ উপস্থাপনা" implementation- হয় এক কিছু বৈধ প্রতিনিধিত্ব থাকতে হবে সংজ্ঞায়িত।

সুতরাং আপনি যদি একটি আরম্ভ করতে ব্যর্থ হন boolবা আপনি যদি এটি কোনও অন্য ধরণের পয়েন্টারের মাধ্যমে ওভাররাইটিংয়ে সফল হন তবে সংকলকটির অনুমানগুলি ভুল হবে এবং অনির্ধারিত আচরণটি ঘটবে। আপনাকে সতর্ক করা হয়েছিল:

৫০) এই আন্তর্জাতিক স্ট্যান্ডার্ড দ্বারা "অপরিজ্ঞাত" হিসাবে বর্ণিত উপায়ে একটি বুলি মান ব্যবহার করা, যেমন একটি অনিবার্যতম স্বয়ংক্রিয় বস্তুর মান পরীক্ষা করে, এটি এমন আচরণ করতে পারে যে এটি সত্য বা মিথ্যা নয়। (§6.9.1 এর মৌলিক প্রকারের প্যারা 6-তে পাদটীকা)


11
" trueমান পূর্ণসংখ্যা 1 এর মতো হতে হবে না" বিভ্রান্তিকর is নিশ্চিত, প্রকৃত বিট প্যাটার্ন পারে অন্য কিছু হতে, কিন্তু পরোক্ষভাবে রূপান্তরিত / উন্নীত (শুধুমাত্র আপনি ভিন্ন অন্য কোনো মান দেখতে না true/ false), trueসবসময় 1, এবং falseসর্বদা0 । অবশ্যই, এই সংকলকটি এই সংকলকটি যে কৌশলটি ব্যবহার করার চেষ্টা করছে তা ব্যবহার করতে অক্ষম হবে (এটি ব্যবহার করে যে boolএর আসল বিট প্যাটার্নটি কেবলমাত্র হতে পারে 0বা 1), সুতরাং এটি ওপির সমস্যার সাথে সম্পর্কিত নয়।
শ্যাডোএ্যাঞ্জার

4
@ শ্যাডোএ্যাঞ্জার আপনি সর্বদা সরাসরি অবজেক্টের উপস্থাপনাটি পরীক্ষা করতে পারেন।
টিসি

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

3
হ্যাঁ, সংযোজনকারীদের (যেমন রিয়েল-ওয়ার্ল্ড সি ++ বাস্তবায়ন) অপ্টিমাইজ করা প্রায়শই কখনও কখনও এমন কোড নির্গত হয় যা boolকিছুটা 0বা বিট-প্যাটার্নের উপর নির্ভর করে 1। তারা boolমেমরি থেকে এটি পড়ার সময় বা পুনরায় বুলেটিনাইজ করে না (বা কোনও ফাংশন আর্গ ধারণকারী একটি রেজিস্টার)। এই উত্তরটি এটাই বলছে। উদাহরণ : gcc4.7 + + নিখুত করতে return a||bকরতে or eax, ediফিরে একটি ফাংশন মধ্যে bool, অথবা MSVC নিখুত করতে a&bকরতে test cl, dl। x86 গুলি testসামান্য দিকের and , সুতরাং যদি cl=1এবং dl=2পরীক্ষা অনুসারে পতাকা সেট করে cl&dl = 0
পিটার

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

52

ফাংশনটি নিজেই সঠিক, তবে আপনার পরীক্ষামূলক প্রোগ্রামে, বিবৃতিটি যে ফাংশনটি বলে তা অনির্ধারিত ভেরিয়েবলের মান ব্যবহার করে অনির্ধারিত আচরণের কারণ হয়।

বাগটি কলিং ফাংশনে রয়েছে এবং কোড পর্যালোচনা বা কলিং ফাংশনের স্থির বিশ্লেষণের মাধ্যমে এটি সনাক্ত করা যায়। আপনার সংকলক এক্সপ্লোরার লিঙ্কটি ব্যবহার করে, সিসি 8.2 সংকলকটি বাগটি সনাক্ত করে। (সম্ভবত আপনি ঝাঁকুনির বিরুদ্ধে একটি বাগ রিপোর্ট ফাইল করতে পারেন যে এটি সমস্যাটি খুঁজে পায় না)।

অপরিজ্ঞাত আচরণের অর্থ হ'ল যে কোনও কিছু ঘটতে পারে, যার মধ্যে প্রোগ্রামটি অন্তর্ভুক্ত না করা আচরণের সূত্রপাতকারী ইভেন্টের পরে কয়েকটি লাইন ক্র্যাশ করে।

বিশেষ দ্রষ্টব্য। "অপরিবর্তিত আচরণের কারণ _____ হতে পারে?" সর্বদা "হ্যাঁ" হয়। এটি আক্ষরিক অর্থেই সংজ্ঞায়িত আচরণের সংজ্ঞা।


2
প্রথম ধারাটি কি সত্য? নিছক একটি অনির্কিত ট্রিগার ইউবি অনুলিপি করা হয়bool ?
জোশুয়া সবুজ

10
@ জোশুয়াগ্রিন দেখুন [dcl.init] / 12 "যদি কোনও মূল্যায়নের মাধ্যমে যদি একটি অনির্দিষ্ট মান উত্পন্ন হয় তবে নিম্নলিখিত বিষয়গুলি ব্যতীত আচরণটি অপরিজ্ঞাত:" (এবং এই ক্ষেত্রে কোনওটিরই ব্যতিক্রম নেই bool)।
এমএম

8
@ জোশুয়াগ্রিন এবং এর কারণ হ'ল আপনার যদি এমন কোনও প্ল্যাটফর্ম থাকতে পারে যা আপনি যদি কোনও ধরণের কিছু অবৈধ মান অ্যাক্সেস করেন তবে একটি হার্ডওয়্যার ত্রুটি ট্রিগার করে। এগুলিকে মাঝে মধ্যে "ট্র্যাপ উপস্থাপনা" বলা হয়।
ডেভিড শোয়ার্টজ

7
ইটানিয়াম, অস্পষ্ট থাকা সত্ত্বেও, এমন একটি সিপিইউ যা এখনও উত্পাদনে রয়েছে, তার ফাঁদ মান রয়েছে এবং এতে কমপক্ষে দুটি আধা-আধুনিক সি ++ সংকলক রয়েছে (ইন্টেল / এইচপি)। এটা আক্ষরিক হয়েছে true, falseএবং not-a-thingBooleans জন্য মান।
এমএসএলটার

3
ফ্লিপ দিকে, "স্ট্যান্ডার্ডের জন্য কোনও নির্দিষ্ট পদ্ধতিতে কোনও প্রক্রিয়াজাতকরণের জন্য সমস্ত সংকলকগুলির কি দরকার" এর উত্তর সাধারণত "না" হয়, এমনকি / বিশেষত যে কোনও মানের সংকলককে এটি করা উচিত তা স্পষ্টভাবে; আরও সুস্পষ্ট কিছু হ'ল, স্ট্যান্ডার্ডের লেখকদের আসলে এটি বলার কম প্রয়োজন হওয়া উচিত।
সুপারক্যাট

23

একটি বুল কেবল অভ্যন্তরীণভাবে trueএবং এর জন্য অভ্যন্তরীণভাবে প্রয়োগকরণ-নির্ভর মানগুলি ধরে রাখার অনুমতি দেয় falseএবং উত্পন্ন কোডটি ধরে নিতে পারে যে এটি কেবল এই দুটি মানের একটি ধারণ করবে hold

সাধারণত, বাস্তবায়ন পূর্ণসংখ্যা ব্যবহার করবে 0জন্য falseএবং 1জন্য trueমধ্যে ধর্মান্তর প্রক্রিয়া সহজ করার জন্য boolএবং int, এবং if (boolvar)হিসাবে একই কোড জেনারেট if (intvar)। সেক্ষেত্রে, কেউ ভাবতে পারেন যে অ্যাসাইনমেন্টের ত্রৈমাসিকের জন্য উত্পন্ন কোডটি সূচক হিসাবে মানটিকে দুটি স্ট্রিংয়ের পয়েন্টারের অ্যারে রূপে ব্যবহার করবে, অর্থাৎ এটি এমন কিছুতে রূপান্তরিত হতে পারে:

// the compile could make asm that "looks" like this, from your source
const static char *strings[] = {"false", "true"};
const char *whichString = strings[boolValue];

যদি boolValueঅবিচ্ছিন্ন করা হয়, এটি আসলে কোনও পূর্ণসংখ্যার মান ধরে রাখতে পারে, যার ফলে stringsঅ্যারের সীমানার বাইরে প্রবেশের কারণ হতে পারে ।


1
@ সিডস ধন্যবাদ। তাত্ত্বিকভাবে, অভ্যন্তরীণ উপস্থাপনাগুলি তারা / থেকে পূর্ণসংখ্যাতে কীভাবে ফেলেছিল তার বিপরীত হতে পারে তবে এটি বিকৃত হবে।
বার্মার

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

3
@ রেমজ আমি উত্পন্ন কোডটি কিসের সমতুল্য হতে পারে তা দেখানোর জন্য কেবল অ্যারেটি ব্যবহার করছি, প্রস্তাব দিচ্ছি না যে আসলে কেউ এটি লিখবে।
বার্মার

1
@Remz ঢেলে সাজানো boolকরার intসঙ্গে *(int *)&boolValueএবং ডিবাগিং উদ্দেশ্যে এটি মুদ্রণ, যদি ছাড়া আর কিছু দেখতে 0বা 1যখন এটি ক্র্যাশ। যদি এটি হয় তবে এটি তাত্পর্যটি অনেকটা নিশ্চিত করে যে সংকলক ইনলাইনটিকে অপ্টিমাইজ করছে - যদি কোনও অ্যারে হিসাবে এটি ক্র্যাশ হচ্ছে কেন তা ব্যাখ্যা করে।
হ্যাভনার্ড

2
@ এসএমএলটাররা: std::bitset<8>আমার সমস্ত আলাদা পতাকাঙ্কের জন্য আমাকে সুন্দর নাম দেয় না। তারা কীসের উপর নির্ভর করে, এটি গুরুত্বপূর্ণ হতে পারে।
মার্টিন বোনার

15

আপনার প্রশ্নের প্রচুর সংক্ষিপ্তসার করে, আপনি জিজ্ঞাসা করছেন যে সি ++ স্ট্যান্ডার্ড কোনও সংকলককে একটি অনুমান করার অনুমতি দেয় কি না? bool কেবল '0' বা '1' এর অভ্যন্তরীণ সংখ্যাগত উপস্থাপনা থাকতে পারে এবং এইভাবে ব্যবহার করতে পারে?

মানটি এ এর ​​অভ্যন্তরীণ প্রতিনিধিত্ব সম্পর্কে কিছুই বলে না bool। এটি কেবলমাত্র boolএকটি int(বা তদ্বিপরীত) এ কাস্ট করার সময় কী ঘটে তা সংজ্ঞায়িত করে । বেশিরভাগ ক্ষেত্রে, এই অবিচ্ছেদ্য রূপান্তরগুলির কারণে (এবং লোকেরা তাদের পরিবর্তে বরং বেশি নির্ভর করে) এই সংকলকটি 0 এবং 1 ব্যবহার করবে তবে এটি করতে হবে না (যদিও এটি এটি যে কোনও নিম্ন স্তরের এবিআই ব্যবহার করে তা সীমাবদ্ধতার সম্মান করতে হবে) )।

সুতরাং, সংকলকটি যখন এটি দেখেছিল তখন তার ' ' বা ' ' বিট নিদর্শনগুলির মধ্যে রয়েছে এবং এটির মতো মনে হয় এমন কিছু boolকরার জন্য অধিকারী entitled মান তাই আপনি যদি এবং 1 এবং 0, যথাক্রমে কম্পাইলার প্রকৃতপক্ষে নিখুত অনুমতি দেওয়া হয় হয় থেকে । অন্যান্য মজাদার আচরণ সম্ভব!booltruefalsetruefalsestrlen5 - <boolean value>

এখানে যেমন বারবার বলা হয়েছে, অপরিজ্ঞাত আচরণের ফলাফল রয়েছে অনির্ধারিত। সহ তবে সীমাবদ্ধ নয় not

  • আপনার কোড যেমনটি আশা করেছিলেন তেমন কাজ করছে
  • আপনার কোড এলোমেলো সময়ে ব্যর্থ
  • আপনার কোডটি মোটেই চালিত হচ্ছে না।

অপরিশোধিত আচরণ সম্পর্কে প্রতিটি প্রোগ্রামারকে কী জানতে হবে তা দেখুন

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