سؤال

نقوم حاليًا بتطوير طلب للحصول على MSP430 MCU ، ونواجه بعض المشكلات الغريبة. اكتشفنا أن إعلان المصفوفات تربط نطاقًا بعد إعلان المتغيرات "الطبيعية" ، أحيانا يسبب ما يبدو أنه سلوك غير محدد. مثله:

foo(int a, int *b);

int main(void)
{
    int x = 2;
    int arr[5];

    foo(x, arr);

    return 0;
}

تم تمرير FOO مؤشرًا كمتغير ثانٍ ، ذلك أحيانا لا يشير إلى arr مجموعة مصفوفة. نتحقق من ذلك عن طريق التنقل الفردي من خلال البرنامج ، ونرى أن قيمة متغير ARR ARRAY-AS-A-A في النطاق الرئيسي ليست هي نفس قيمة متغير مؤشر B في نطاق FOO. ولا ، هذا ليس قابلاً للتكرار حقًا ، لقد لاحظنا هذا السلوك من حين إلى آخر.

يمكن ملاحظته حتى قبل تنفيذ سطر واحد من وظيفة FOO ، فإن معلمة المؤشر المرتفع (B) لا تشير ببساطة إلى العنوان الذي هو ARR.

يبدو أن تغيير المثال يحل المشكلة ، مثل هذا:

foo(int a, int *b);

int main(void)
{
    int arr[5];
    int x = 2;

    foo(x, arr);

    return 0;
}

هل لدى أي شخص أي مدخلات أو تلميحات حول سبب تجربة هذا السلوك؟ أو تجارب مماثلة؟ يحدد دليل البرمجة MSP430 أن الرمز يجب أن يتوافق مع مواصفات ANSI C89. وهكذا كنت أتساءل عما إذا كان يقول أنه يجب الإعلان عن المصفوفات قبل المتغيرات غير الجيرية؟

أي مدخلات على هذا سيكون موضع تقدير.


تحديث

Adam Shiemke و Tomlogic:

أتساءل ما الذي يحدده C89 حول طرق مختلفة لتهيئة القيم ضمن الإعلانات. هل يُسمح لك بكتابة شيء مثل:

int bar(void)
{
    int x = 2;
    int y;

    foo(x);
}

وإذا كان الأمر كذلك ، فماذا عن:

int bar(int z)
{
    int x = z;
    int y;

    foo(x);
}

هل هذا مسموح؟ أفترض أن ما يلي يجب أن يكون غير قانوني C89:

int bar(void)
{
    int x = baz();
    int y;

    foo(x);
}

شكرا لك مقدما.


تحديث 2تم حل المشكلة. في الأساس ، نحن في حالة تعطيل المقاطعات قبل استدعاء الوظيفة (FOO) وبعد إعلانات المتغيرات. نحن قادرون على إعادة إنتاج المشكلة في مثال بسيط ، ويبدو أن الحل هو إضافة عبارة _NOP () بعد استدعاء مقاطعة تعطيل.

إذا كان أي شخص مهتمًا ، يمكنني نشر المثال الكامل لإعادة إنتاج المشكلة ، والإصلاح؟

شكرا لجميع المدخلات في هذا.

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

المحلول

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

إذا وجدت حشرة مترجم ، تحقق أيضًا من التحسين. لقد رأيت الأخطاء مثل هذا المقدمة من قبل المحسن.

نصائح أخرى

هذا يبدو وكأنه حشرة المترجم.

إذا كنت تستخدم مثالك الأول (المليئة الإشكالية) واكتب استدعاء وظيفتك كـ foo(x, &arr[0]);, ، هل ترى نفس النتائج؟ ماذا لو قمت بتهيئة الصفيف مثل int arr[5] = {0};؟ لا ينبغي على أي من هؤلاء تغيير أي شيء ، ولكن إذا فعلوا ذلك ، فسيشير إلى حشرة البرمجي.

في سؤالك المحدث:

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

يبدو كما لو أن المقاطعة التي تعطيل الجوهرية/الوظيفة/الماكرو (أو مع ذلك معطل المقاطعات) قد تسبب "تخطي" تعليمات أو شيء من هذا القبيل. سأقوم بالتحقيق فيما إذا كانت مشفرة/تعمل بشكل صحيح.

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

بالنسبة لـ C89 ، يجب إعلان المتغيرات في قائمة في بداية النطاق قبل أي مهمة. C99 يسمح لك بخلط المهمة إعلان. لذا:

{ 
    int x; 
    int arr[5];

    x=5;
...

هو أسلوب C89 القانوني. أنا مندهش من أن المترجم الخاص بك لم يرمي نوعًا من الخطأ في ذلك إذا لم يدعم C99.

على افتراض أن الكود الحقيقي أكثر تعقيدًا ، فإن هناك بعض الأشياء التي سأتحقق منها ، ضع في اعتبارك أنها تخمن:

هل يمكن أن تفيض المكدس في بعض الأحيان؟ إذا كان الأمر كذلك ، فهل يمكن أن يكون هذا بعض القطع الأثرية من "الدفاع عن المكدس" من قبل المترجم/UC؟ هل القيمة غير الصحيحة لـ & foo تقع داخل نطاق ذاكرة يمكن التنبؤ بها؟ إذا كان الأمر كذلك ، فهل هذا النطاق له أي أهمية (داخل المكدس ، إلخ)؟

هل لدى MCU430 نطاقات مختلفة للذاكرة وذاكرة الوصول العشوائي التي تتناولها؟ هذا هو ، هل مساحة العنوان لـ RAM 16BIT بينما عنوان البرنامج مساحة 24 بت؟ الموافقة المسبقة عن علم لديها مثل هذه الهندسة المعمارية على سبيل المثال. إذا كان الأمر كذلك ، فمن الممكن أن يتم تخصيص ARR كـ ROM (24bit) وتتوقع الوظيفة مؤشرًا إلى ذاكرة الوصول العشوائي (16bit) ، وسيعمل الكود عندما تم تخصيص ARR في أول 16 بت من مساحة العنوان ولكنه من الطوب إذا كان ذلك فوق هذا النطاق .

ربما لديك في مكان ما في برنامجك في ذاكرة غير قانونية تكتب التي تفسد مكدتك.

هل ألقيت نظرة على التفكيك؟

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