سؤال

توجد في شركتي قاعدة ترميز تنص على أنه بعد تحرير أي ذاكرة، قم بإعادة تعيين المتغير إلى NULL.على سبيل المثال ...

void some_func () 
{
    int *nPtr;

    nPtr = malloc (100);

    free (nPtr);
    nPtr = NULL;

    return;
}

أشعر أنه في حالات مثل الكود الموضح أعلاه، فإن الإعداد على NULL ليس له أي معنى.أم هل فاتني شيء؟

إذا لم يكن هناك معنى في مثل هذه الحالات، فسوف أتحدث مع "فريق الجودة" لإزالة قاعدة الترميز هذه.من فضلك النصيحة.

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

المحلول

ووضع مؤشرات غير المستخدمة إلى NULL هو اسلوب دفاعي، وحماية ضد الحشرات مؤشر متدلية. إذا تم الوصول مؤشر التعلق بعد تحريرها، يمكنك قراءة أو الكتابة ذاكرة عشوائية. إذا تم الوصول إلى مؤشر فارغة، وتحصل على حادث تحطم فوري على معظم النظم، وأقول لك على الفور ما هو الخطأ.

لالمتغيرات المحلية، قد يكون من المجدي قليلا إذا كان "واضحا" أن المؤشر لا الوصول إليها بعد الآن بعد اطلاق سراحه، لذلك هذا الاسلوب هو أكثر ملاءمة للبيانات الأعضاء والمتغيرات العالمية. وحتى بالنسبة للمتغيرات المحلية، قد يكون نهجا جيدا إذا استمرت وظيفة بعد أن يتم الافراج عن الذاكرة.

لإكمال النمط، يجب عليك أيضا تهيئة المؤشرات إلى NULL قبل الحصول على تعيين قيمة المؤشر الحقيقية.

نصائح أخرى

ووضع مؤشر إلى NULL بعد free هو ممارسة مريبة التي غالبا ما شاع بأنه "البرمجة الجيدة" حكم على فرضية خاطئة واضح. انها واحدة من تلك الحقائق المزيفة التي تنتمي إلى "الأصوات الصحيحة" الفئة ولكن في الواقع تحقيق أي شيء على الإطلاق المفيد (ويؤدي أحيانا إلى عواقب سلبية).

ويزعم، ووضع مؤشر إلى NULL بعد المفترض free لمنع اللعين "مزدوجة الحرة" المشكلة عندما يتم تمرير قيمة المؤشر نفسه لfree أكثر من مرة. في الواقع رغم ذلك، في 9 حالات من أصل 10 حدوث "مزدوجة الحرة" المشكلة الحقيقية عندما <م> مختلفا وتستخدم الأجسام مؤشر عقد قيمة المؤشر نفس الحجج لfree. وغني عن القول، ووضع مؤشر إلى NULL بعد يحقق free لا شيء على الإطلاق لمنع المشكلة في مثل هذه الحالات.

وبطبيعة الحال، فإنه من الممكن أن تصل الى مشكلة "مزدوجة الحرة" عند استخدام نفس الكائن مؤشر كحجة لfree. ومع ذلك، في حالات مثل الواقع التي تشير عادة مشكلة مع البنية المنطقية العام للقانون، وليس مجرد عرضي "ضعف الحرة". والطريقة الصحيحة للتعامل مع المشكلة في مثل هذه الحالات هي لمراجعة وإعادة النظر في هيكل رمز من أجل تجنب الوضع عندما يتم تمرير نفس المؤشر إلى free أكثر من مرة. في مثل هذه الحالات وضع المؤشر إلى NULL والنظر في مشكلة "ثابت" ليست أكثر من محاولة لكنس المشكلة تحت السجادة. انها ببساطة لن ينجح في الحالة العامة، لأن المشكلة مع هيكل رموز وسوف تجد دائما طريقة أخرى ليعبر عن نفسه.

وأخيرا، إذا تم التعليمات البرمجية المصممة خصيصا لتعتمد على قيمة المؤشر يجري NULL أم لا NULL، فإنه على ما يرام تماما لتعيين قيمة المؤشر إلى NULL بعد free. ولكن كقاعدة عامة "الممارسات الجيدة" (كما في "دوما تعيين المؤشر إلى NULL بعد free") هو، مرة أخرى، وهمية معروفة وغير مجدية جدا، وغالبا ما يتبعه بعض لأسباب دينية بحتة، مثل الفودو .

ومعظم الردود قد ركزت على منع مزدوج مجانا، ولكن وضع المؤشر إلى NULL له فائدة أخرى. بمجرد تحرير مؤشر، أن الذاكرة غير متوفرة ليتم تخصيصها عن طريق مكالمة أخرى لmalloc. إذا كنت لا تزال لديها مؤشر الأصلي من حولك قد ينتهي مع خلل فيها محاولة استخدام مؤشر بعد حر والفاسدين بعض المتغيرات الأخرى، ومن ثم البرنامج يدخل حالة غير معروفة وجميع أنواع الأشياء السيئة يمكن أن يحدث (العطل إذا كنت "محظوظا، تلف البيانات إذا كنت سيئ الحظ). إذا كنت قد وضعت المؤشر إلى NULL بعد مجانا، فإن أي محاولة لقراءة / الكتابة من خلال هذا المؤشر في وقت لاحق من شأنه أن يؤدي إلى segfault، وهو أفضل من تلف الذاكرة العشوائية بشكل عام.

لكلا السببين، فإنه يمكن أن يكون فكرة جيدة لتعيين المؤشر إلى NULL بعد مجانا (). انها ليست دائما ضرورية، وإن كان. على سبيل المثال، إذا كان المتغير مؤشر يخرج من نطاق فور مجانا ()، وليس هناك ما يدعو إلى تعيين إلى NULL.

يعتبر هذا ممارسة جيدة لتجنب الكتابة فوق الذاكرة.في الوظيفة المذكورة أعلاه، يكون ذلك غير ضروري، ولكن في كثير من الأحيان عندما يتم ذلك يمكن العثور على أخطاء في التطبيق.

جرب شيئًا مثل هذا بدلاً من ذلك:

#if DEBUG_VERSION
void myfree(void **ptr)
{
    free(*ptr);
    *ptr = NULL;
}
#else
#define myfree(p) do { void ** __p = (p); free(*(__p)); *(__p) = NULL; } while (0)
#endif

يتيح لك DEBUG_VERSION تحرير ملفات التعريف في تعليمات تصحيح الأخطاء البرمجية، ولكن كلاهما متماثلان من الناحية الوظيفية.

يحرر:تم اضافة فعل...بينما على النحو المقترح أدناه، وذلك بفضل.

وإذا وصلت المؤشر الذي كان مجانا () د، قد كسر أم لا. يمكن تخصيصها تلك الذاكرة إلى جزء آخر من البرنامج ومن ثم تحصل تلف الذاكرة،

إذا قمت بتعيين المؤشر إلى NULL، ثم إذا كان يمكنك الوصول إليه، البرنامج تعطل دائما مع segfault. لا أكثر ،، في بعض الأحيان يعمل ''، لا أكثر ،، حوادث في الطريق unpredictible ''. انها وسيلة أسهل التصحيح.

ووضع المؤشر إلى الذاكرة free'd يعني أن أي محاولة للوصول إلى الذاكرة من خلال مؤشر سوف تعطل على الفور، بدلا من التسبب في سلوك غير معرف. فإنه يجعل من الاسهل بكثير لتحديد مكان ساءت الأمور.

وأستطيع أن أرى حجتك: منذ nPtr هو الخروج من نطاق الحق بعد nPtr = NULL، لا يبدو أن يكون سببا للتعيين إلى NULL. ومع ذلك، في حالة لأحد أعضاء struct أو أي مكان آخر حيث المؤشر لن فورا خارج النطاق، فإنه من المنطقي. انها ليست على الفور واضحا ما إذا كان هذا المؤشر سوف تستخدم مرة أخرى عن طريق الرمز الذي لا ينبغي استخدامه.

وعلى الأرجح جاء فيها حكم من دون تمييز بين هاتين الحالتين، لأنه أكثر صعوبة لفرض تلقائيا القاعدة، ناهيك عن المطورين لمتابعة ذلك. فإنه لا يضر لوضع مؤشرات لNULL بعد كل مجانا، لكنه لا يملك إمكانات لافتا إلى مشاكل كبيرة.

وعلة الأكثر شيوعا في ج هو ضعف مجانا. في الأساس أن تفعل شيئا من هذا القبيل

free(foobar);
/* lot of code */
free(foobar);

وينتهي سيئة جدا، وOS محاولة لتحرير بعض ذاكرة محررة بالفعل وعموما segfault. لذا فإن الممارسة السليمة لوضع لNULL، حتى تتمكن من تقديم الاختبار والاختيار إذا كنت بحاجة حقا لتحرير هذه الذاكرة

if(foobar != null){
  free(foobar);
}

وكما تجدر الإشارة إلى أن free(NULL) لن تفعل أي شيء لذلك لم يكن لديك لكتابة بيان إذا. أنا لست حقا المعلم OS ولكن أنا جدا حتى الآن معظم أنظمة تشغيل من شأنه ان تحطم على ضعف مجانا.

وهذا هو أيضا السبب الرئيسي وراء كل اللغات مع جمع القمامة (جافا، DOTNET) كانت فخورة جدا من عدم وجود هذه المشكلة، وكذلك عدم وجود لترك للمطورين إدارة الذاكرة ككل.

والفكرة وراء هذا، هو وقف إعادة الاستخدام العرضي للمؤشر سراحه.

وهذا (يمكن) أن يكون في الواقع مهمة. على الرغم من أنك تحرير الذاكرة، يمكن أن الجزء الأخير من البرنامج تخصيص شيء جديد يحدث على الأرض في الفضاء. أن المؤشر القديم الخاص بك الآن يشير إلى قطعة صالحة من الذاكرة. ومن الممكن بعد ذلك أن شخص ما استخدام المؤشر، مما أدى إلى حالة برنامج غير صالحة.

إذا NULL من المؤشر، ثم أي محاولة لاستخدام هو الذهاب إلى 0x0 dereference وتحطم هناك حق، والتي من السهل التصحيح. مؤشرات عشوائية لافتا إلى ذاكرة عشوائية من الصعب التصحيح. من الواضح ليس من الضروري ولكن بعد ذلك هذا هو السبب في انها في وثيقة أفضل الممارسات.

ومن معيار ANSI C:

void free(void *ptr);
<اقتباس فقرة>   

وظيفة خالية يتسبب في الفضاء   المشار إليه بواسطة PTR يمكن deallocated،   وهذا هو، تتاح للمزيد   توزيع. إذا PTR هو مؤشر لاغية،   يحدث أي إجراء. خلاف ذلك، إذا كان   حجة لا يتطابق مؤشر   عاد في وقت سابق من قبل calloc،   malloc، أو realloc وظيفة، أو إذا   وقد يتم deallocated الفضاء من قبل   الدعوة إلى تحرير أو realloc، السلوك   غير معرف.

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

void safe_free(void** ptr)
{
  free(*ptr);
  *ptr = NULL;
}

وأجد أن هذا القليل من المساعدة كما هو الحال في تجربتي عند وصول الناس إلى تخصيص الذاكرة تحريرها دائما تقريبا لأن لديهم مؤشر آخر لأنه في مكان ما. وبعد ذلك يتعارض مع معيار آخر الترميز الشخصي الذي هو "تجنب فوضى غير مجدية"، لذلك أنا لا تفعل ذلك كما أعتقد أنه نادرا ما تساعد ويجعل رمز أقل قليلا للقراءة.

ولكن - وأنا لن تعيين متغير فارغة إن لم يكن من المفترض أن يتم استخدامها مرة أخرى المؤشر، ولكن في كثير من الأحيان على مستوى التصميم العالي يعطيني سببا لتعيين فارغة على أي حال. على سبيل المثال إذا كان المؤشر عضوا في فئة ولقد حذف ما يشير إلى ذلك "العقد" إذا كنت مثل الطبقة هو أن هذا العضو سوف يشير إلى شيء صحيح في أي وقت لذلك يجب ان تترك فارغة لهذا السبب. التمييز صغير ولكن أعتقد مهم.

في ج ++ من المهم أن تكون دائما التفكير الذي <م> تمتلك هذه البيانات عند تخصيص بعض الذاكرة (إلا إذا كنت تستخدم مؤشرات الذكية ولكن حتى ذلك الحين مطلوب بعض التفكير). وهذه العملية تميل إلى أن تؤدي إلى مؤشرات يجري عموما عضوا في بعض الطبقة وعموما كنت تريد فئة أن تكون في حالة صالحة في جميع الأوقات، وأسهل طريقة للقيام بذلك هو وضع متغير العضو إلى NULL للإشارة إلى أنها تشير إلى أي شيء الآن.

وثمة نمط شائع لتعيين كافة مؤشرات الأعضاء إلى NULL في منشئ ولها دعوة المدمر حذف أي مؤشرات إلى البيانات أن التصميم الخاص بك يقول تلك الفئة <م> تمتلك . ومن الواضح في هذه الحالة لديك لتعيين المؤشر إلى NULL عند حذف شيء للإشارة إلى أنك لا تملك أي بيانات من قبل.

ولتلخيص ذلك، نعم أنا في كثير من الأحيان تعيين المؤشر إلى NULL بعد حذف شيء، ولكن هذا كجزء من تصميم والأفكار أكبر على من يملك البيانات بدلا من بسبب عمياء التالية قاعدة القياسية الترميز. وأود أن لا تفعل ذلك في المثال الخاص بك وأنا أعتقد أن هناك أي فائدة للقيام بذلك ويضيف "فوضى" الذي في تجربتي تماما كما هو المسؤول عن الخلل ورمز سيئة لأن هذا النوع من الشيء.

ومؤخرا جئت عبر نفس السؤال بعد أن كان يبحث عن الجواب. وصلت إلى هذا الاستنتاج:

ومن أفضل الممارسات، ويجب على المرء أن يتبع هذا لجعله المحمولة على جميع أنظمة (جزءا لا يتجزأ).

وfree() هي وظيفة المكتبة، والتي تختلف عن التغيرات واحدة منصة، لذلك يجب أن لا نتوقع أن بعد مرور المؤشر لهذه الوظيفة وبعد تحرير الذاكرة، سيتم تعيين هذا المؤشر إلى NULL. قد لا يكون هذا هو الحال بالنسبة لبعض المكتبات تنفيذها لمنصة.

وحتى يذهب دائما ل

free(ptr);
ptr = NULL;

وهذه القاعدة هي مفيدة عندما كنت في محاولة لتجنب السيناريوهات التالية:

1) أن يكون لديك وظيفة طويلة حقا مع منطق معقد وإدارة الذاكرة وكنت لا ترغب في إعادة بطريق الخطأ مؤشر إلى الذاكرة حذف في وقت لاحق وظيفة.

2) المؤشر متغير عضو من الفئة التي لديها سلوك معقد إلى حد ما، وكنت لا ترغب في إعادة بطريق الخطأ مؤشر إلى الذاكرة المحذوفة في وظائف أخرى.

في السيناريو الخاص بك، فإنه لا يجعل بأسره الكثير من معانيها، ولكن إذا كانت وظيفة للحصول على فترة أطول، قد يهم.

وتستطيع القول بأن تعيين إلى NULL في الواقع قد قناع خطأ منطقي في وقت لاحق، أو في حالة ما إذا كنت تفترض أنها صحيحة، كنت لا تزال تعطل على NULL، لذلك لا يهم.

في عام، أنصح لك لتعيين إلى NULL عندما كنت تعتقد انها فكرة جيدة، وليس عناء عندما كنت تعتقد أنه لا يستحق ذلك. التركيز بدلا من ذلك على كتابة وظائف قصيرة والطبقات مصممة بشكل جيد.

لإضافة إلى ما آخرون قال، طريقة جيدة لاستخدام المؤشر للتحقق دائما ما إذا كان المؤشر صالح أو لا. شيء من هذا القبيل:


if(ptr)
   ptr->CallSomeMethod();

وبمناسبة بشكل صريح المؤشر كما NULL بعد تخليصه يسمح لهذا النوع من الاستخدام في C / C ++.

وهذا قد يكون أكثر حجة لتهيئة كافة المؤشرات إلى NULL، ولكن شيئا من هذا القبيل يمكن أن يكون علة متستر جدا:

void other_func() {
  int *p; // forgot to initialize
  // some unrelated mallocs and stuff
  // ...
  if (p) {
    *p = 1; // hm...
  }
}

void caller() {
  some_func();
  other_func();
}

وp ينتهي في نفس المكان على المكدس كما nPtr السابق، لذلك قد لا تزال تحتوي على مؤشر على ما يبدو صالحا. تكليف *p قد الكتابة كل أنواع الأشياء غير ذات صلة، وتؤدي إلى الخلل قبيحة. وخاصة إذا كان المترجم تهيئة المتغيرات المحلية مع صفر في وضع التصحيح ولكن لا يتم تشغيل لا أمثل مرة واحدة على. لذا فإن التصحيح يبني لا تظهر أي علامات على علة في حين نسخ الإصدار تفجير عشوائيا ...

وتعيين المؤشر الذي تم مؤخرا إطلاق سراح لNULL ليس إلزاميا ولكن ممارسة جيدة. بهذه الطريقة، يمكنك تجنب 1) باستخدام سراح أشار 2) تحريرها towice

وإعدادات مؤشر إلى NULL هو حماية امام نظيره يسمى خالية المزدوج - الحالة عندما مجانا () يسمى أكثر من مرة لنفس العنوان بدون إعادة توزيع الكتلة في هذا العنوان

ويؤدي مجانا مزدوجة لسلوك غير معرف - عادة كومة الفساد أو تحطمها البرنامج فورا. داعيا مجانا () لمؤشر فارغة لا يفعل شيئا، وبالتالي يتم ضمان أن تكون آمنة.

ولذا فإن أفضل الممارسات إلا إذا كنت الآن على وجه اليقين أن المؤشر يترك مجالا فورا أو في وقت قريب جدا بعد مجانا () هو وضع هذا المؤشر إلى NULL بحيث حتى لو مجانا () يسمى مرة أخرى ويطلق عليه الآن لمؤشر NULL وتهرب سلوك غير معرف.

والفكرة هي أنه إذا حاولت dereference المؤشر حظر صالح يعد بعد تخليصه، وتريد أن تفشل الصلب (segfault) بدلا من بصمت وفي ظروف غامضة.

ولكن ... كن حذرا. ليست كل أنظمة يسبب segfault إذا كنت dereference NULL. على (على الأقل بعض إصدارات) AIX، * (كثافة العمليات *) 0 == 0، وسولاريس ديه التوافق اختياري مع هذا AIX "ميزة".

لالسؤال الأصلي: وضع المؤشر إلى NULL مباشرة بعد تحرير محتويات هو مضيعة للوقت، شريطة رمز يفي بجميع المتطلبات يتم تصحيحه تماما ولن يتم تعديلها مرة أخرى. من ناحية أخرى، مدافعا NULLing مؤشر الذي تم إطلاق سراح يمكن أن تكون مفيدة جدا عندما يقوم شخص ما يضيف تفكير كتلة جديدة من التعليمات البرمجية تحت مجانا ()، عندما تصميم وحدة الأصلي غير صحيحة، وفي حالة منه البق -compiles ولكن توجد الآن؟ ر-دو-ما-I-الفاقة.

في أي نظام، هناك هدف لا يمكن الحصول عليه لجعله أسهل للالشيء الصحيح، وتكلفة غير القابل للاختزال من قياسات غير دقيقة. في C نحن عرضت مجموعة من وأدوات قوية جدا حادة جدا، والتي يمكن أن تخلق أشياء كثيرة في أيدي العمال المهرة، وإلحاق كل أنواع الإصابات الاستعارية عند التعامل معها بشكل غير صحيح. بعض من الصعب فهم أو استخدام بشكل صحيح. والناس، ويجري بشكل طبيعي تجنب المخاطرة، تفعل أشياء غير منطقية مثل فحص مؤشر لقيمة NULL قبل استدعاء مجانا مع ذلك ...

المشكلة القياس هي أنه كلما حاولت تقسيم جيدة من أقل جيدة، وأكثر تعقيدا في القضية، وعلى الأرجح تحصل على قياس غامضة. إذا كان الهدف هو القيام حفاظ على الممارسات الجيدة فقط، ثم بعض منها غامضة الحصول على قذف بها مع الواقع ليست جيدة. إذا كان هدفك هو القضاء على يست جيدة، ثم الغموض يمكن أن يقيم مع الصالح. الهدفين، والحفاظ على جيد فقط أو القضاء سيئة بشكل واضح، ويبدو أن على طرفي نقيض، ولكن عادة ما يكون هناك مجموعة ثالثة هذا لا هذا ولا ذاك، بعض من الاثنين معا.

قبل إجراء الحال مع قسم الجودة، حاول البحث في قاعدة البيانات علة لنرى كيف كثير من الأحيان، إذا من أي وقت مضى، تسببت القيم مؤشر غير صالحة المشاكل التي كان لا بد من كتابتها. إذا كنت تريد أن تجعل الفرق الحقيقي، وتحديد المشكلة الأكثر شيوعا في التعليمات البرمجية الإنتاج الخاص واقتراح ثلاث طرق لمنع ذلك

وهناك سببان:

تجنب تعطل عندما نقرا مزدوجا تحرير

RageZ في <لأ href = "https://stackoverflow.com/questions/ 1879168 / لماذا-وضع واحد في رمية لاغية بعد خالية-في-ج الدعوة / 1879173 # 1879173 "> السؤال مكررة .

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

وعلة الأكثر شيوعا في ج هو ضعف   مجانا. أساسا لديك شيء من هذا القبيل   أن

free(foobar);
/* lot of code */
free(foobar);
     

وينتهي سيئة جدا، حاول OS   لتحرير بعض ذاكرة محررة بالفعل و   عموما segfault. ذلك خير   الممارسة في تعيين لNULL، لذلك كنت   يمكن أن تجعل اختبار ومعرفة ما اذا كنت حقا   تحتاج إلى تحرير هذه الذاكرة

if(foobar != NULL){
  free(foobar);
}
     

وكما تجدر الإشارة إلى أن free(NULL)   لن تفعل أي شيء لذلك لم يكن لديك ل   إرسال بيان إذا. انا لست   حقا المعلم OS لكن أنا جميلة حتى   الآن معظم أنظمة تشغيل من شأنه ان تحطم على ضعف   مجانا.

     

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

تجنب استخدام بالفعل إطلاق سراح المؤشرات

مارتن الخامس Löwis في <لأ href = "الشبكي: / /stackoverflow.com/questions/1025589/setting-variable-to-null-after-free/1025604#1025604">another الجواب .

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

ووضع مؤشرات غير المستخدمة إلى NULL هو   أسلوب دفاعي، وحماية ضد   التعلق البق المؤشر. إذا كان التعلق   يتم الوصول إليها المؤشر بعد تحريرها،   يمكنك قراءة أو الكتابة عشوائي   ذاكرة. إذا تم الوصول مؤشر فارغة،   تحصل حادث تحطم فوري على الأكثر   نظم، وأقول لك على الفور ما   الخطأ.

     

لالمتغيرات المحلية، قد يكون   قليلا من العبث إذا كان   "واضحة" أن المؤشر لا   الوصول بعد الآن بعد اطلاق سراحه، لذلك   هذا النمط هو أكثر ملاءمة ل   بيانات الأعضاء والمتغيرات العالمية. حتى في   للمتغيرات المحلية، قد تكون جيدة   نهج إذا استمرت وظيفة   بعد تحرير الذاكرة.

     

لإكمال النمط، يجب عليك أيضا   تهيئة المؤشرات إلى NULL قبل   يحصلون على تعيين المؤشر الحقيقي   قيمة.

وكما لديك فريق ضمان الجودة في مكان، اسمحوا لي أن أضيف نقطة ثانوية حول QA. بعض الأدوات QA الآلي للقيام بمهام C إرادة العلم لتحرير مؤشرات بأنها "مهمة جدوى من ptr". على سبيل المثال PC-الوبر / FlexeLint من Gimpel البرمجيات يقول tst.c 8 Warning 438: Last value assigned to variable 'nPtr' (defined at line 5) not used

وهناك طرق لمنع الرسائل بشكل انتقائي، لذلك يمكنك الاستمرار في تلبية كل متطلبات QA، يجب أن يقرر فريقك ذلك.

يُنصح دائمًا بالإعلان عن متغير المؤشر باستخدام باطل مثل،

int *ptr = NULL;

دعنا نقول، بتر يشير إلى 0x1000 عنوان الذاكرة.بعد الاستخدام free(ptr), ، يُنصح دائمًا بإبطال متغير المؤشر من خلال الإعلان مرة أخرى عن to باطل.على سبيل المثال:

free(ptr);
ptr = NULL;

إذا لم يتم إعادة الإعلان عنها باطل, ، فإن متغير المؤشر يستمر في الإشارة إلى نفس العنوان (0x1000)، يسمى متغير المؤشر هذا أ المؤشر المتدلي.إذا قمت بتحديد متغير مؤشر آخر (على سبيل المثال، س) وتخصيص العنوان ديناميكيًا للمؤشر الجديد، هناك فرصة لأخذ نفس العنوان (0x1000) بواسطة متغير المؤشر الجديد.إذا كنت تستخدم نفس المؤشر (بتر) وقم بتحديث القيمة على العنوان المشار إليه بنفس المؤشر (بتر)، فسينتهي البرنامج بكتابة قيمة إلى المكان الذي س ويشير (منذ ص و س يشيرون إلى نفس العنوان (0x1000)).

على سبيل المثال

*ptr = 20; //Points to 0x1000
free(ptr);
int *q = (int *)malloc(sizeof(int) * 2); //Points to 0x1000
*ptr = 30; //Since ptr and q are pointing to the same address, so the value of the address to which q is pointing would also change.

وقصة قصيرة طويلة: أنت لا تريد بطريق الخطأ (خطأ) الوصول إلى العنوان الذي كنت قد تحررت. لأن عند تحرير عنوان، فإنك تسمح عنوان في كومة التي ستخصص بعض التطبيقات الأخرى.

ولكن، إذا لم يتم تعيين المؤشر إلى NULL، وعن طريق الخطأ في محاولة لنزع إشارة المؤشر، أو تغيير قيمة هذا العنوان؛ لا زال بإمكانك فعلها. وليست شيئا كنت تريد منطقيا إلى DO.

لماذا لا يزال يمكنني الوصول إلى موقع ذاكرة بأنني تحررت؟ للأسباب التالية: قد يكون لديك تحرير الذاكرة، ولكن المتغير المؤشر لا تزال لديها معلومات حول عنوان ذاكرة الكومة. لذلك، على استراتيجية دفاعية، يرجى تعيين إلى NULL.

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