Подтвердить что ты не робот

Как сделать gcc предупреждать undefined struct?

У меня есть структура, определенная в .h

struct buf_stats {
   // ***
};

затем в .c файле

struct buf_stats *bs = malloc(sizeof(struct buf_states*)) ;

где buf_states - опечатка.

но gcc не предупреждает меня, хотя я использовал -Wall

и эта ошибка/опечатка стоила мне 3 часа, чтобы узнать.

Как сделать gcc предупреждать undefined struct как это?

4b9b3361

Ответ 1

В вашем коде

  struct buf_stats *bs = malloc(sizeof(struct buf_states*)) ;

неверно по многим причинам, например

  • Вы используете тип undefined (как вы упомянули)
  • Вы выделяете меньше памяти (выделяя вместо типа указатель на тип)

Но ваш компилятор не может много помочь в _this_case для данного конкретного типа ошибок, поскольку

  • указатель на (любой) тип в платформе имеет определенный размер, для чего структура (т.е. тип переменной, на которую она указывает) не обязательно должна быть полной (определенной). Это причина, по которой мы можем иметь структуры для самореференции, правильно?

  • malloc() не имеет понятия о типе целевой переменной. Он просто считывает аргумент нужного размера, возвращает указатель (который имеет тип void *) в выделенную память и при назначении, который изменяется на целевой тип. Невозможно рассчитать несоответствие в целевом размере (типе) с выделенным объемом памяти.

Самый удобный и простой способ избежать подобных ошибок - не использовать жесткий код непосредственно в качестве операнда sizeof, скорее, использовать ссылку на переменную.

Что-то вроде

 struct buf_stats *bs = malloc(sizeof *bs) ; // you can write that as (sizeof (*bs)) also
                                             // sizeof *bs === sizeof (struct buf_stats)

что эквивалентно

 struct buf_stats *bs = malloc(sizeof(struct buf_stats)) ;

но является более надежным и менее подверженным ошибкам.

Примечания:

  • Вам не нужна скобка, если операнд не является именем типа.
  • Этот оператор не нуждается в каких-либо изменениях при изменении типа целевой переменной bs.

Ответ 2

Вы не можете. Использование выражения типа struct foo * (указатель на некоторый тип структуры) объявляет эту структуру как неполный тип. Размер неизвестен, но это не обязательно для размера указателя.

Тем не менее, код выглядит неправильно, так как вам нужен размер структуры (не), поэтому со следующим кодом:

struct buf_stats *bs = malloc(sizeof(struct buf_states));

вы получите ошибку.

Там лучший способ написать такой код:

struct buf_stats *bs = malloc(sizeof *bs);

Выражение *bs имеет правильный тип для sizeof, даже если вы позже измените тип.