PTHREAD_COND_INITIALIZER против шины

#c #pthreads #conditional #mutex #splint

#c #pthreads #условные операторы #мьютекс #splint

Вопрос:

У меня есть следующий код

 static pthread_mutex_t watchdogMutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t watchdogCond = PTHREAD_COND_INITIALIZER;
  

и я получаю следующие ошибки / предупреждения при использовании Splint

Статический watchdogCond._data._mutex, инициализированный нулевым значением: watchdogCond._data._mutex = (void )0 Ссылка без нулевой аннотации присваивается или инициализируется НУЛЕМ. Используйте /@null@*/, чтобы объявить ссылку как возможно нулевой указатель. (Используйте -nullassign, чтобы запретить предупреждение)

В чем проблема с этим и представляет ли это реальную опасность?

Ответ №1:

Похоже, что у splint проблема с явной инициализацией указателей как null. и ему нужен какой-то комментарий с переопределением аннотации, чтобы отключить предупреждение. Я бы просто последовал его совету и использовал -nullassign опцию, чтобы отключить это предупреждение. Нет ничего плохого или вредного в том, что делает ваш код, или в том, как реализация определила макросы инициализатора. Это просто у splint иррациональные страхи.

Комментарии:

1. Спасибо. В Spint что-то говорится о том, что после этой ошибки, о которой я упоминал выше, проверка источника не может продолжаться.

2. Используйте -nullassign опцию, чтобы отключить эту проверку.

Ответ №2:

Кажется, что pthread_mutex_t это непрозрачный указатель (вы могли бы отследить typedef , чтобы выяснить). В Splint указатели не обнуляются по умолчанию. Если вы хотите иметь указатель с возможностью обнуления, вы должны объявить его с семантической аннотацией /*@null@*/ , например:

 char * ptr1;
/*@null@*/ char * ptr2;

ptr1 = NULL; /* warning: implicitly not-nullable pointer */
ptr2 = NULL; /* OK: explicitly nullable pointer */
  

Согласно руководству, существует 3 варианта, касающиеся нулевого состояния:

  • null Возможно, нулевой указатель.
  • notnull Ненулевой указатель.
  • relnull Ослабьте проверку на нуль. Нет ошибок, когда ему присваивается значение NULL или когда он используется в качестве ненулевого указателя.

Преимущество использования указателей, не обнуляемых, заключается в том, что вам не нужно проверять их каждый раз, когда вы получаете один из них. Например, вы могли бы аннотировать параметр функции как /*@notnull@*/ , и тогда вам не требуется проверять if(pointer == NULL) , прежде чем разыменовывать его. Это сокращает проверку и упрощает ваш код.

Опасность игнорирования этих предупреждений заключается в том, что, если вы сообщаете Splint, что определенный указатель не может быть нулевым, и позже вы пытаетесь присвоить NULL ему, этот нулевой указатель может в конечном итоге разыменоваться, и программа может завершиться сбоем.

На мой взгляд, ваша фактическая проблема заключается в политике Splint, которая рассматривает все указатели неявно как ненулевые. Это вынуждает вас аннотировать все ваши указатели, возможно, нулевые.