Могут ли разные уровни оптимизации привести к функционально различному коду? - PullRequest
44 голосов
/ 16 июня 2011

Мне любопытно, какие свободы имеет компилятор при оптимизации.Давайте ограничим этот вопрос GCC и C / C ++ (любая версия, любой вариант стандарта):

Можно ли написать код, который ведет себя по-разному, в зависимости от того, с каким уровнем оптимизации он был скомпилирован?

Пример, который я имею в виду, - это печать разных фрагментов текста в различных конструкторах в C ++ и получение разницы в зависимости от того, выбраны ли копии (хотя я не смог заставить такую ​​вещь работать).

Подсчет тактов не допускается.Если у вас есть пример для компилятора без GCC, мне тоже было бы любопытно, но я не могу его проверить.Бонусные баллы за пример в C.: -)

Редактировать: Код примера должен соответствовать стандарту и не содержать неопределенного поведения с самого начала.

Редактировать 2: Получил несколько отличных ответов!Позвольте мне немного поднять ставку: код должен составлять правильно сформированную программу и соответствовать стандартам, а также должен компилироваться для корректных, детерминированных программ на каждом уровне оптимизации.(Это исключает такие вещи, как условия гонки в плохо сформированном многопоточном коде.) Также я ценю, что это может повлиять на округление с плавающей запятой, но давайте не будем об этом говорить.Репутация щедрости на первом законченном примере, соответствующем (духу) этих условий;25, если это связано со злоупотреблением строгим псевдонимом.(При условии, что кто-то показывает мне, как отправить вознаграждение кому-то другому.)

Ответы [ 13 ]

0 голосов
/ 20 марта 2019

Две разные программы на Си:

foo6.c

void p2(void);

int main() {
    p2();
    return 0;
}

bar6.c

#include <stdio.h>

char main;

void p2() {
    printf("0x%x\n", main);
}

Когда оба модуля скомпилированы в одну исключительную с уровнями оптимизации одини ноль, они распечатывают два разных значения.0x48 для -O1 и 0x55 для -O0

Снимок экрана терминала

Вот пример его работы в моей среде

0 голосов
/ 10 ноября 2018

такой же исходный код, как source code

до включения -finline-small-functions и после включения -finline-small-functions

Before enable -finline-small-functions

After enable -finline-small-functions

-finline-small-functions можно включить в -O2 / -O3

0 голосов
/ 16 июня 2011

Сегодня у меня есть интересный пример из моего курса по ОС.Мы проанализировали некоторый программный мьютекс, который может быть поврежден при оптимизации, поскольку компилятор не знает о параллельном выполнении.

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

...