উনল সমস্ত সাধারণ অনির্ধারিত আচরণ যা একটি C++ প্রোগ্রামার সম্পর্কে জানা উচিত?




সি++ বই (9)

আমার পছন্দের "টেমপ্লেটগুলির তাত্ক্ষণিকতায় অসীম পুনরাবৃত্তি" কারণ আমি বিশ্বাস করি এটিই একমাত্র যেখানে সংজ্ঞায়িত সময়ে অনির্ধারিত আচরণ ঘটে।

সমস্ত সাধারণ অনির্ধারিত আচরণ যা একটি C ++ প্রোগ্রামার সম্পর্কে জানা উচিত?

বলুন, ভালো লেগেছে:

a[i] = i++;


ইশারা

  • একটি নিল পয়েন্টার deferenferencing
  • আকারের শূন্য একটি "নতুন" বরাদ্দ দ্বারা ফিরে একটি পয়েন্টার deferenferencing
  • বস্তুগুলির পয়েন্টার ব্যবহার করে যার জীবনকাল শেষ হয়েছে (উদাহরণস্বরূপ, বরাদ্দকৃত বস্তু বা মুছে ফেলা বস্তুগুলি স্ট্যাক করুন)
  • একটি পয়েন্টার Dereferencing যে এখনও স্পষ্টভাবে চালু করা হয় নি
  • পয়েন্টার গাণিতিক সম্পাদন যা একটি অ্যারের সীমানা (উপরে বা নীচে) বাইরে ফলাফল ফলন করে।
  • একটি অ্যারের শেষে অতিক্রম একটি অবস্থানে পয়েন্টার deferenferencing।
  • পয়েন্টারগুলিকে অসঙ্গতিপূর্ণ প্রকারের বস্তুতে রূপান্তর করা হচ্ছে
  • memcpy বাফার অনুলিপি করার জন্য memcpy ব্যবহার করে ।

বাফার overflows

  • নেতিবাচক, অফসেটে বা বস্তুর আকারের বাইরে (বস্তু / হিপ ওভারফ্লো) কোনও বস্তু বা অ্যারে পড়তে বা লিখতে

সংখ্যাগরিষ্ঠ overflows

  • স্বাক্ষর পূর্ণসংখ্যা ওভারফ্লো
  • গাণিতিকভাবে সংজ্ঞায়িত না যে একটি অভিব্যক্তি মূল্যায়ন
  • একটি নেতিবাচক পরিমাণ দ্বারা বাম স্থানান্তর মান (নেতিবাচক পরিমাণের দ্বারা ডান পাল্টা বাস্তবায়ন সংজ্ঞায়িত হয়)
  • সংখ্যায় বিট সংখ্যাগুলির চেয়ে বড় বা সমান পরিমাণের দ্বারা মানগুলি স্থানান্তরিত করা হচ্ছে (যেমন int64_t i = 1; i <<= 72 অনির্ধারিত)

ধরন, কাস্ট এবং কনস্ট

  • একটি সংখ্যাসূচক মানকে এমন মানের মধ্যে নিক্ষেপ করা যা লক্ষ্যের ধরন দ্বারা উপস্থাপিত হয় না (সরাসরি বা স্ট্যাটিক_কাস্টের মাধ্যমে)
  • এটি স্বয়ংক্রিয়ভাবে নির্ধারিত হওয়ার আগে একটি স্বয়ংক্রিয় পরিবর্তনশীল ব্যবহার করে (যেমন, int i; i++; cout << i; )
  • একটি সংকেত প্রাপ্তিতে volatile বা sig_atomic_t ছাড়া অন্য কোন বস্তুর মান ব্যবহার করে
  • তার জীবদ্দশায় একটি স্ট্রিং আক্ষরিক বা অন্য কোন কনস্টেবল পরিবর্তন করতে চেষ্টা
  • Preprocessing সময় একটি ব্যাপক স্ট্রিং আক্ষরিক সঙ্গে একটি সংকীর্ণ Concatenating

ফাংশন এবং টেমপ্লেট

  • একটি মান-ফিরতি ফাংশন থেকে একটি মান ফেরত না (সরাসরি বা একটি ট্রাই-ব্লক থেকে প্রবাহিত করে)
  • একই সত্তাটির জন্য একাধিক ভিন্ন সংজ্ঞা (বর্গ, টেমপ্লেট, গণনা, ইনলাইন ফাংশন, স্ট্যাটিক সদস্য ফাংশন, ইত্যাদি)
  • টেমপ্লেট তাত্ক্ষণিক অসীম পুনর্মিলন
  • বিভিন্ন প্যারামিটার বা প্যারামিটার ব্যবহার করে একটি ফাংশন কলিং এবং লিংক যা ফাংশন ব্যবহার হিসাবে সংজ্ঞায়িত করা হয়।

গলি

  • স্ট্যাটিক স্টোরেজ সময়সীমার সঙ্গে বস্তুর ধ্বংসাবশেষ ধ্বংস
  • আংশিকভাবে overlapping বস্তুর বরাদ্দ ফলাফল
  • তার স্ট্যাটিক বস্তুর সূচনাকালে একটি ফাংশন পুনরাবৃত্তি আবার
  • ভার্চুয়াল ফাংশন মেকিং তার নির্মাতা বা ধ্বংসকারী থেকে একটি বস্তুর বিশুদ্ধ ভার্চুয়াল ফাংশন কল
  • বস্তুগুলির nonstatic সদস্যদের উল্লেখ করা হয় না নির্মাণ করা হয়েছে বা ইতিমধ্যে ধ্বংস করা হয়েছে

উত্স ফাইল এবং প্রপ্রোকাসিং

  • একটি নন-খালি উৎস ফাইল যা একটি নতুন লাইনের সাথে শেষ না হয়, বা ব্যাকস্ল্যাশের সাথে শেষ হয় (C ++ 11 এর আগে)
  • একটি অক্ষর অনুসরণ করে একটি অক্ষর যা একটি চরিত্র বা স্ট্রিং ধ্রুবক (এটি সি ++ 11 এ বাস্তবায়ন-সংজ্ঞায়িত) নির্দিষ্ট পালানো কোডগুলির অংশ নয়।
  • বাস্তবায়ন সীমা অতিক্রম করা (নেস্টেড ব্লকের সংখ্যা, একটি প্রোগ্রামে ফাংশন সংখ্যা, উপলব্ধ স্ট্যাক স্পেস ...)
  • Preprocessor সংখ্যাসূচক মান যে একটি long int দ্বারা প্রতিনিধিত্ব করা যাবে না
  • একটি ফাংশন মত ম্যাক্রো সংজ্ঞা বাম দিকে Preprocessing নির্দেশিকা
  • গতিশীলভাবে একটি #if অভিব্যক্তি মধ্যে সংজ্ঞায়িত টোকেন #if

শ্রেণীবদ্ধ করা

  • স্ট্যাটিক স্টোরেজ সময়কাল সঙ্গে একটি প্রোগ্রাম ধ্বংস সময় প্রস্থান কল

একমাত্র টাইপ যার জন্য সি ++ একটি আকার গ্যারান্টি char । এবং আকার 1। অন্যান্য সমস্ত ধরনের আকার প্ল্যাটফর্ম নির্ভরশীল।


const_cast<> ব্যবহার করে const_cast<> ness stripping পরে একটি ধ্রুবক const_cast<> :

const int i = 10; 
int *p =  const_cast<int*>( &i );
*p = 1234; //Undefined

অনির্দিষ্ট আচরণের পাশাপাশি, একইভাবে অভদ্র বাস্তবায়ন-সংজ্ঞায়িত আচরণও রয়েছে

অনির্ধারিত আচরণ যখন কোনো প্রোগ্রাম এমন কিছু করে যা ফলাফল দ্বারা নির্দিষ্ট করা হয় না।

বাস্তবায়ন-সংজ্ঞায়িত আচরণ একটি প্রোগ্রাম দ্বারা একটি কর্ম যার ফলাফল মান দ্বারা সংজ্ঞায়িত করা হয় না, কিন্তু যা বাস্তবায়ন ডকুমেন্টেশন প্রয়োজন। স্ট্যাক ওভারফ্লো প্রশ্ন থেকে "Multibyte Character Literals" একটি উদাহরণ, এটি কি সি কম্পাইলার যা এই সংকলন করতে ব্যর্থ হয়?

আপনি যখন পোর্টিং শুরু করেন তখন বাস্তবায়ন-সংজ্ঞায়িত আচরণ কেবল আপনার কামড় দেয় (তবে কম্পাইলারের নতুন সংস্করণে আপগ্রেড করাও পোর্টিং হয়!)


কম্পাইলারটি একটি অভিব্যক্তিটির মূল্যায়ন অংশগুলিকে পুনঃ-আদেশের জন্য মুক্ত করা (অর্থ মনে করা অপরিবর্তিত)।

মূল প্রশ্ন থেকে:

a[i] = i++;

// This expression has three parts:
(a) a[i]
(b) i++
(c) Assign (b) to (a)

// (c) is guaranteed to happen after (a) and (b)
// But (a) and (b) can be done in either order.
// See n2521 Section 5.17
// (b) increments i but returns the original value.
// See n2521 Section 5.2.6
// Thus this expression can be written as:

int rhs  = i++;
int lhs& = a[i];
lhs = rhs;

// or
int lhs& = a[i];
int rhs  = i++;
lhs = rhs;

ডবল চেক লকিং। এবং এক সহজ ভুল করতে।

A* a = new A("plop");

// Looks simple enough.
// But this can be split into three parts.
(a) allocate Memory
(b) Call constructor
(c) Assign value to 'a'

// No problem here:
// The compiler is allowed to do this:
(a) allocate Memory
(c) Assign value to 'a'
(b) Call constructor.
// This is because the whole thing is between two sequence points.

// So what is the big deal.
// Simple Double checked lock. (I know there are many other problems with this).
if (a == null) // (Point B)
{
    Lock   lock(mutex);
    if (a == null)
    {
        a = new A("Plop");  // (Point A).
    }
}
a->doStuff();

// Think of this situation.
// Thread 1: Reaches point A. Executes (a)(c)
// Thread 1: Is about to do (b) and gets unscheduled.
// Thread 2: Reaches point B. It can now skip the if block
//           Remember (c) has been done thus 'a' is not NULL.
//           But the memory has not been initialized.
//           Thread 2 now executes doStuff() on an uninitialized variable.

// The solution to this problem is to move the assignment of 'a'
// To the other side of the sequence point.
if (a == null) // (Point B)
{
    Lock   lock(mutex);
    if (a == null)
    {
        A* tmp = new A("Plop");  // (Point A).
        a = tmp;
    }
}
a->doStuff();

// Of course there are still other problems because of C++ support for
// threads. But hopefully these are addresses in the next standard.

ভেরিয়েবল শুধুমাত্র একবার একটি এক্সপ্রেশন (একযোগে একযোগে টেকনিক পয়েন্টের মধ্যে) আপডেট করা যেতে পারে।

int i =1;
i = ++i;

// Undefined. Assignment to 'i' twice in the same expression.

মেমরি অঞ্চল overlapping মধ্যে কপি করতে memcpy ব্যবহার করে। উদাহরণ স্বরূপ:

char a[256] = {};
memcpy(a, a, sizeof(a));

আচরণ সি স্ট্যান্ডার্ড অনুযায়ী অনির্ধারিত, যা সি ++ 03 স্ট্যান্ডার্ড দ্বারা subsumed হয়।

7.21.2.1 memcpy ফাংশন

সংক্ষিপ্তসার

1 / # অকার্যকর * memcpy অন্তর্ভুক্ত (অকার্যকর * S1 সীমাবদ্ধ, কনস অকার্যকর * s2, size_t এন সীমাবদ্ধ);

বিবরণ

2 / memcpy ফাংশন s1 দ্বারা নির্দেশিত বস্তু মধ্যে S2 নির্দেশ বস্তু থেকে এন অক্ষর কপি। অনুলিপি করা বস্তুর মধ্যে অনুলিপি সঞ্চালিত হলে, আচরণ অনির্ধারিত হয়। Returns 3 memcpy ফাংশন s1 এর মান প্রদান করে।

7.21.2.2 memmove ফাংশন

সংক্ষিপ্তসার

1 # অকার্যকর * memmove অন্তর্ভুক্ত (অকার্যকর * s1, কং অকার্যকর * s2, size_t এন);

বিবরণ

2 memmove ফাংশন s1 দ্বারা নির্দেশিত বস্তুর মধ্যে বস্তু থেকে n অক্ষর কপি অক্ষর কপি। অনুলিপি সংঘটিত হয় যেমন বস্তু থেকে এন অক্ষরগুলি স 2 দ্বারা নির্দেশিত হয় তা প্রথম অক্ষরের অস্থায়ী অ্যারে রূপে অনুলিপি করা হয় যা s1 এবং s2 দ্বারা নির্দেশিত বস্তুগুলি ওভারল্যাপ করে না এবং তারপরে অস্থায়ী অ্যারের এন অক্ষগুলি অনুলিপি করা হয় বস্তু s1 দ্বারা নির্দেশিত। রিটার্নস

3 memmove ফাংশন s1 এর মান প্রদান করে।


একটি নতুন সংকলন ইউনিটগুলিতে নামস্থান-স্তরের অবজেক্টগুলি শুরু করার জন্য একে অপরের উপর নির্ভর করে না, কারণ তাদের প্রাথমিককরণ ক্রমটি অনির্দিষ্ট।





c++-faq