سؤال

لقد كنت أحاول الخروج جبيرة مع برنامج C ، كتبت مؤخرًا وأحاول فهم وإزالة التحذيرات التي يعطيها. واحد أفهمه ولكن لا أستطيع أن أفهم كيفية إزالته يأتي من مقتطف الكود التالي:

static MyType_t *findById(const int id)
{
    int i;

    for (i = 0; i < MY_ARR_SIZE; i++) {
            if (my_arr[i].id == NOT_SET) {
                    /* Items are sorted so that items with 
                    NOT_SET as ID are at the end of the array */
                    break;
            }
            if (my_arr[i].id == id) {
                    return &(my_arr[i]);
            }
    }
    return NULL; 
}

Splint ليس سعيدًا لأن الوظيفة يمكن أن تعود فارغة ، ولكن في هذه الحالة يكون من المنطقي تمامًا.

حاولت استخدام /@nullwhenfalse@/ ولكن يبدو أنه يعمل فقط إذا كانت الوظيفة تُرجع صحيحًا / خطأ وحاول أيضًا تغيير الكود لاستخدام Retval وحاول كلاهما /@باطل@/ و /@relnull@/ أمام الإعلان ، لكن هذه لم تفعل شيئًا.

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

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

المحلول

يجب عليك التحقق من استخدام /*@null@* / أمام الإعلان.

في الإصدار التالي القابل للتجميع من مثالك ، فإنه يزيل التحذير (باستخدام Splint 3.1.2):

typedef struct { int id; } MyType_t;
#define NOT_SET -1
#define MY_ARR_SIZE 20
static MyType_t my_arr[MY_ARR_SIZE];

/*@null@*/ static MyType_t *findById(const int id)
{
    int i;
    for (i = 0; i < MY_ARR_SIZE; i++) {
            if (my_arr[i].id == NOT_SET) {
                    /* Items are sorted so that items with 
                    NOT_SET as ID are at the end of the array */
                    break;
            }
            if (my_arr[i].id == id) {
                    return &(my_arr[i]);
            }
    }
    return NULL;
}

int main() {
    (void)findById(10);
    return 0;
}

إذا كان لا يزال لديك تحذير مماثل ، فهل يمكن أن يكون عن جزء آخر من الكود الخاص بك؟

نصائح أخرى

splint -nullret سوف يسحق هذا التحذير (على الصعيد العالمي) الذي قد يكون أو لا يكون ما تريد القيام به. في بعض الحالات ، ما لم تكن كذلك بالتأكيد الحصول على نوع عودة فارغة صحيح ، ربما أنت تريد التحذير.

لقد اختبرت مثال جيروم ، وقد صمت التحذير من هذه الوظيفة بالذات.

مهما فعلت ، أود أن أقترح بشدة عدم تضمين رموز الشظية مباشرة في المصدر ، ولكن بدلاً من ذلك لف هذه الوظيفة في الماكرو.

على سبيل المثال ، على مشروع الببغاء ، لديّ وحدات الماكرو هذه

#  define ARGIN(x)                    /*@in@*/ /*@notnull@*/
#  define ARGIN_NULLOK(x)             /*@in@*/ /*@null@*/
    /* The pointer target must be completely defined before being passed */
    /* to the function. */

#  define ARGOUT(x)                   /*@out@*/ /*@notnull@*/
#  define ARGOUT_NULLOK(x)            /*@out@*/ /*@null@*/
    /* The pointer target will be defined by the function */

ثم يتم استخدام وحدات الماكرو حتى نتمكن من استخدام:

void copy_string( ARGOUT(char *target), ARGIN(const char *source ) ) ...

إذا أردنا تغيير كيفية معالجة الحجج Argin () ، فإننا نغيرها في مكان واحد. يمكننا أيضًا دعم ترميزات متعددة لأدوات أو مجمعين متعددين.

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