Эффекты объявления функции чистой или постоянной для GCC, когда это не так

GCC может предложить функции для атрибута pure и атрибута const с флагами -Wsuggest-attribute=pure а также -Wsuggest-attribute=const,

Документация GCC говорит:

Многие функции не имеют эффектов, кроме возвращаемого значения, и их возвращаемое значение зависит только от параметров и / или глобальных переменных. Такая функция может быть подвержена общему исключению подвыражения и оптимизации цикла так же, как и арифметический оператор. Эти функции должны быть объявлены с атрибутом pure.

Но что может произойти, если вы приложите __attribute__((__pure__)) к функции, которая не соответствует приведенному выше описанию и имеет побочные эффекты? Является ли просто вероятность того, что функция будет вызываться меньше, чем вы хотели бы, или возможно создание неопределенного поведения или других серьезных проблем?

Аналогично для __attribute__((__const__)) что еще строже — в документации говорится:

По сути, это просто немного более строгий класс, чем приведенный ниже чистый атрибут, поскольку функция не может читать глобальную память.

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

Я бы предпочел технические ответы с объяснениями реальных возможных сценариев в рамках GCC / G ++, а не обычными »носовые демоны«рукопожатие, которое появляется всякий раз, когда упоминается неопределенное поведение.

0

Решение

Но что может произойти, если вы приложите __attribute__((__pure__))
к функции, которая не соответствует приведенному выше описанию,
и есть ли побочные эффекты?

Именно так. Вот короткий пример:

extern __attribute__((pure)) int mypure(const char *p);

int call_pure() {
int x = mypure("Hello");
int y = mypure("Hello");
return x + y;
}

Моя версия GCC (4.8.4) достаточно умна, чтобы удалить второй вызов mypure (результат 2*mypure()). Теперь представьте, если mypure мы printf — побочный эффект печати строки "Hello" будет потеряно

Обратите внимание, что если я заменю call_pure с

char s[];

int call_pure() {
int x = mypure("Hello");
s[0] = 1;
int y = mypure("Hello");
return x + y;
}

оба вызова будут отправлены (потому что назначение s[0] может изменить выходное значение mypure).

Это просто вероятность того, что функция будет вызываться меньше раз
чем вы хотели бы, или это возможно создать
неопределенное поведение или другие серьезные проблемы?

Ну, это может вызвать UB косвенно. Например. Вот

extern __attribute__((pure)) int get_index();

char a[];
int i;
void foo() {
i = get_index();  // Returns -1
a[get_index()];  // Returns 0
}

Компилятор, скорее всего, отбросит второй вызов get_index() и использовать первое возвращаемое значение -1 что приведет к переполнению буфера (ну, технически, переполнение).

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

Давайте снова возьмем приведенный выше пример с

int call_pure() {
int x = mypure("Hello");
s[0] = 1;
int y = mypure("Hello");
return x + y;
}

Если mypure были аннотированы __attribute__((const))компилятор снова отбросит второй вызов и оптимизирует возврат к 2*mypure(...), Если mypure на самом деле читает sэто приведет к неправильному результату.

РЕДАКТИРОВАТЬ

Я знаю, что вы просили избегать махать руками, но вот несколько общих объяснений. По умолчанию вызов функции блокирует много оптимизаций внутри компилятора, так как он должен рассматриваться как черный ящик, который может иметь произвольные побочные эффекты (изменить любую глобальную переменную и т. Д.). Функция аннотирования с использованием const или pure вместо этого позволяет компилятору трактовать его как выражение, которое позволяет более агрессивную оптимизацию.

Примеров действительно слишком много, чтобы привести. То, что я привел выше, — это обычное исключение подвыражений, но мы также можем легко продемонстрировать преимущества для инвариантов цикла, устранения мертвого кода, анализа псевдонимов и т. Д.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]