إزالة التحذيرات الفارغة في شظية
-
21-09-2019 - |
سؤال
لقد كنت أحاول الخروج جبيرة مع برنامج 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 () ، فإننا نغيرها في مكان واحد. يمكننا أيضًا دعم ترميزات متعددة لأدوات أو مجمعين متعددين.