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

Неправильное использование cool

В проекте C (OpenVPN является рассматриваемым проектом, commit 4029971240b6274b9b30e76ff74c7f689d7d9750), у нас была эмуляция bool

typedef int bool;
#define false 0
#define true 1

и теперь переключитесь на C99 bool

#include <stdbool.h>

Но в проекте есть где-то плохое использование bool. Я знаю, что std bool ведет себя по-другому. Например.

bool t;

t=2;
if ( t == true)
    printf("True!\n");
else
    printf("False!\n");

Вернется True! с stdbool.h и False! с эмуляцией #define.

Мой вопрос Есть ли способ найти эти части кода, которые ведут себя по-разному с stdbool и emulated bool? Возможно, какой-то флаг компилятора я пропустил или хороший промежуточный формат llvm или gcc, который можно отличить?

Это не так просто, как в приведенном выше примере, но должно быть то, что не так просто видеть. Определенно не == true.

UPDATE: Мы обнаружили проблему (у mbuf_set есть int member len). Это глупо, но вопрос все еще остается, как поймать их. Я удивлен, что целые проверки переполнения не улавливают такие вещи:

 static inline bool
 mbuf_len (const struct mbuf_set *ms)
 {
   return ms->len;
 }
4b9b3361

Ответ 1

Вид использования, который вы описываете, является правильным, четко определенным поведением. Поэтому компилятор не выдаст никаких предупреждений. Один из возможных способов - изменить typedef:

typedef enum {false, true} bool;

Это все равно позволит компиляции кода без ошибок (как он определенно), но вы можете принудительно вызывать предупреждения из компилятора или анализатора. Например, clang будет выбирать этот тип с помощью -Weverything:

$ clang -o a a.c -Weverything
a.c:7:11: warning: integer constant not in range of enumerated type 'bool'
      [-Wassign-enum]
        bool n = 2;

Конечно, это не будет проверять время выполнения. Он все равно позволит изменить переменную bool typedef на что-то другое, кроме 0 или 1 (например, через вызов функции или выражение). Единственный способ обнаружить эти экземпляры - использовать отладчик.

Макросы для true и false в stdbool.h предназначены только для типа _Bool. Это связано с тем, что этот тип может содержать только значения 0 и 1; любое значение, которое вы назначаете, которое не равно 0, хранится как 1. Таким образом, для булевого типа гарантируется работа с истинными и ложными макросами.

Без типа _Bool не существует способа, чтобы сам язык делал это для вас напрямую, потому что нет сопоставимого типа, и вы действительно попросите его разрешить, чтобы 2 == 1 возвращал true.

Существует несколько способов реализации такого же поведения, например. используя макрос, такой как BOOL(n) в каждом случае использования переменной n, чтобы обеспечить его значение только 0 или 1. Таким образом, вы получите тот же результат, используя _Bool или int для n. Например:

#define BOOL(n) ((n) != 0 ? 1 : 0 )

bool b = rand() % 100;

if (BOOL(b) == true) ...

Это будет работать, используя stdbool или typedef.

Ответ 2

Извините, долго писать комментарии, так что это не ответ:

Я думаю, что вы должны искать все файлы для таких слов, как true, false,... и просматривать их использование.

IMO, используя автоматические инструменты, возможно, проблема с этим:

int x = true;
int y = 8;

//...

if (x == y) // `true` is not near `if` statement
{
//...

Я предпочитаю просмотр кода вручную, однако это может потребовать много времени.



Все другие предложения, такие как un-define bool, true, false,..., чтобы заставить компилятор давать ошибки, являются просто сложными способами простого поиска. Если компилятор говорит:

"у вас есть идентификатор undefined" true "в строке xyz"

ОК, инструмент поиска говорит:

"У вас есть" истинное "слово в строке zyx"

Я предпочитаю второй способ.