ما هي الشائعة غير معرفة السلوكيات التي مبرمج C++ يجب أن أعرف عنها ؟ [مغلقة]

StackOverflow https://stackoverflow.com/questions/367633

سؤال

ما هي الشائعة غير معرفة السلوكيات التي مبرمج C++ يجب أن أعرف عنها ؟

يقول مثل:

a[i] = i++;

هل كانت مفيدة؟

المحلول

مؤشر

  • Dereferencing a NULL مؤشر
  • Dereferencing مؤشر عادت من "جديد" تخصيص الحجم صفر
  • باستخدام مؤشرات إلى الكائنات التي عمر قد انتهت (على سبيل المثال تخصيص كومة الأشياء أو الكائنات المحذوفة)
  • Dereferencing مؤشر أنه لم يتم حتى الآن بالتأكيد تهيئة
  • أداء المؤشر الحسابي الذي ينتج نتيجة خارج حدود (إما أعلى أو أقل) من صفيف.
  • Dereferencing المؤشر في موقع أبعد من نهاية الصفيف.
  • تحويل مؤشرات إلى كائنات غير المتوافقة أنواع
  • باستخدام memcpy نسخ تداخل النطاقات.

تجاوزات المخزن المؤقت

  • قراءة أو كتابة إلى كائن أو مجموعة في إزاحة هذا هو سلبي ، أو أبعد من حجم هذا الكائن (كومة/كومة تجاوز)

صحيح تجاوزات

  • وقعت تجاوز عدد صحيح
  • تقييم تعبير غير محددة رياضيا
  • اليسار تحويل القيم السلبية مبلغ (صحيح التحولات السلبية المبالغ تنفيذ محددة)
  • تحويل القيم بمبلغ أكبر من أو يساوي عدد البتات في عدد (مثلا ، int64_t i = 1; i <<= 72 غير معرف)

أنواع الزهر Const

  • صب القيمة الرقمية إلى قيمة لا يمكن أن تكون ممثلة من قبل نوع الهدف (إما مباشرة أو عبر static_cast)
  • باستخدام متغير تلقائية من قبل فقد كان بالتأكيد المخصصة (على سبيل المثال ، int i; i++; cout << i;)
  • باستخدام قيمة من أي كائن من نوع آخر من volatile أو sig_atomic_t في تلقي إشارة
  • محاولة تعديل سلسلة حرفية أو أي const الكائن أثناء مدى الحياة
  • وصل ضيق مع مجموعة واسعة من سلسلة حرفية خلال تجهيزها

وظيفة القالب

  • لا إرجاع قيمة من القيمة العودة وظيفة (مباشرة أو عن طريق تتدفق خارج من كتلة try)
  • عدة تعاريف مختلفة لنفس الكيان (الدرجة, قالب, التعداد, مضمنة وظيفة عضو ثابت وظيفة ، إلخ.)
  • لانهائية العودية في إنشاء مثيل من القوالب
  • استدعاء دالة باستخدام معايير مختلفة أو الربط إلى المعلمات والربط أن وظيفة محددة مثل استخدام.

OOP

  • المتتالية التدمير من الكائنات مع ساكنة مدة التخزين
  • نتيجة تكليف متداخلة جزئيا الكائنات
  • بشكل متكرر إعادة إدخال وظيفة خلال التهيئة من الأجسام الساكنة
  • مما يجعل الظاهري المكالمات وظيفة نقية وظائف افتراضية لكائن من منشئ أو المدمر
  • مشيرا إلى nonstatic أعضاء الكائنات التي لم يتم بناؤها أو تم بالفعل تدمير

الملف المصدر و تجهيزها

  • غير فارغة الملف المصدر الذي لا ينتهي السطر, أو ينتهي مع خط مائل عكسي (قبل C++11)
  • خط مائل عكسي يليه حرف ليس هو الجزء المحدد هروب رموز في حرف أو سلسلة ثابتة (هذا هو تنفيذ محددة في C++11).
  • تزيد على تنفيذ حدود (عدد من كتل متداخلة عدد من الوظائف في البرنامج متوفر مساحة مكدس ...)
  • المعالج القيم الرقمية التي لا يمكن أن تكون ممثلة من قبل long int
  • تجهيزها التوجيه على الجانب الأيسر من وظيفة مثل تعريف الماكرو
  • حيوي توليد المعرفة رمزية في #if التعبير

إلى أن تصنف

  • داعيا الخروج خلال تدمير برنامج مع ساكنة مدة التخزين

نصائح أخرى

الأمر الذي معلمات الدالة يتم تقييم هو غير محدد السلوك.(هذا لن يجعل البرنامج تحطم, تنفجر, أو طلب البيتزا...على عكس غير معرف السلوك.)

والشرط الوحيد هو أن جميع المعلمات يجب تقييمها بشكل كامل قبل أن يتم استدعاء الدالة.


هذا:

// The simple obvious one.
callFunc(getA(),getB());

يمكن أن يعادل هذا:

int a = getA();
int b = getB();
callFunc(a,b);

أو هذا:

int b = getB();
int a = getA();
callFunc(a,b);

يمكن أن تكون أما ؛ تصل إلى مترجم.والنتيجة أن المسألة اعتمادا على الآثار الجانبية.

ومترجم حر في إعادة ترتيب الأجزاء تقييم تعبير (على افتراض المعنى هو لم يتغير).

ومن السؤال الأصلي:

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.

وبلدي المفضل هو "العودية لانهائية في مثيل القوالب" لأنني أعتقد أنه هو الوحيد حيث يحدث سلوك غير معرف في وقت التحويل البرمجي.

وتعيين إلى ثابت بعد تجريد constness باستخدام const_cast<>:

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

إلى جانب غير معرف سلوك, هناك أيضا سيئة على قدم المساواة تنفيذ-تعريف السلوك.

غير معرف السلوك يحدث عندما يكون البرنامج لا شيء النتيجة التي لا يحددها المعيار.

تنفيذ-تعريف السلوك هو عمل برنامج والنتيجة التي لا يحددها معيار ، ولكن التنفيذ هو مطلوب الوثيقة.مثال على ذلك هو "أحرف متعددة البايت حرفية" من تجاوز سعة مكدس السؤال هل هناك برنامج التحويل البرمجي C الذي فشل في ترجمة هذا ؟ .

تنفيذ-تعريف السلوك فقط لدغات عندما تبدأ ترقية (ولكن الترقية إلى الإصدار الجديد من برنامج التحويل البرمجي هو أيضا ترقية!)

وقد يتم تحديث المتغيرات مرة واحدة فقط في تعبير (مرة واحدة من الناحية الفنية بين نقاط تسلسل).

int i =1;
i = ++i;

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

فهم أساسي من مختلف القيود البيئية.القائمة الكاملة في القسم 5.2.4.1 C المواصفات.هنا هي عدد قليل ،

  • 127 المعلمات في تعريف الدالة
  • 127 الحجج في استدعاء دالة
  • 127 المعلمات في تعريف الماكرو
  • 127 الحجج في ماكرو واحد الاحتجاج
  • 4095 الشخصيات بطريقة منطقية المصدر خط
  • 4095 الأحرف في سلسلة أحرف الحرفي أو واسعة سلسلة حرفية (بعد سلسلة)
  • 65535 بايت في كائن (في بيئة استضافة فقط)
  • 15nesting مستويات #includedfiles
  • 1023 حالة تسميات مفتاح بيان (باستثناء تلك anynested التبديل البيانات)

في الحقيقة كنت مندهشا قليلا في الحد من 1023 حالة تسميات بيان التبديل يمكنني فورسي أن يجري تجاوز التعليمات البرمجية التي تم إنشاؤها/ليكس/موزعي إلى حد ما easially.

إذا كانت هذه هي حدود تجاوز لديك غير معرف سلوك (حوادث, ثغرات أمنية ، الخ...).

صحيح أنا أعلم أن هذا من ج المواصفات ، ولكن C++ أسهم هذه الأساسية يدعم.

وعن طريق memcpy لنسخ بين مناطق الذاكرة متداخلة. على سبيل المثال:

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

وتكون غير معرفة السلوك وفقا لC الموحدة، التي تصنف من قبل ستاندرد C ++ 03.

7.21.2.1 وظيفة memcpy

<اقتباس فقرة>   

وخلاصة

     

1 / تتضمن # الفراغ * memcpy (باطل * تقييد S1، CONST   الفراغ * تقييد S2، size_t ن)؛

     

والوصف

     

و2 / وظيفة memcpy   نسخ ن الأحرف من الكائن أشارت إليه S2 إلى كائن   المشار إليه بواسطة s1 و. إذا نسخ يحدث بين الكائنات التي تتداخل،   سلوك غير معرف. عودة 3 وظيفة memcpy ترجع   قيمة S1.

7.21.2.2 وظيفة memmove

<اقتباس فقرة>   

وخلاصة

     

1 # تشمل الفراغ * memmove (الفراغ * S1، S2 CONST الفراغ *، size_t   ن)؛

     

والوصف

     

و2 نسخ وظيفة memmove ن الأحرف من الكائن أشارت إلى   من S2 إلى الكائن المشار إليه بواسطة s1 و. نسخ تجري كما لو كان   ن الأحرف من الكائن أشارت إليه S2 يتم نسخ لأول مرة في   مجموعة مؤقتة من شخصيات ن أن لا تتداخل الكائنات   المشار إليه بواسطة S1 و S2، ثم الأحرف ن من مؤقتة   يتم نسخ مجموعة إلى كائن أشار إليه S1. عودة

     

و3 وظيفة memmove إرجاع قيمة S1.

والنوع الوحيد الذي C ++ يضمن حجم char. وحجم 1. حجم من جميع أنواع أخرى هو منصة تعتمد.

والأجسام على مستوى النطاق في وحدات تجميع مختلفة لا ينبغي أبدا أن تعتمد على بعضها البعض للتهيئة، لأجل التهيئة الخاصة غير معرف.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top