Без кода это сложно, но вот некоторые вещи, которые я видел раньше.
Отладка операторов печати часто оказывается единственным пользователем значения, о котором знает компилятор. Без оператора print компилятор считает, что он может покончить с любыми операциями и требованиями к памяти, которые в противном случае потребовались бы для вычисления или сохранения этого значения.
Подобное происходит, когда в список аргументов вашего оператора печати включены побочные эффекты.
printf("%i %i\n", x, y = x - z);
Другой тип ошибки может быть:
for( i = 0; i < END; i++) {
int *a = &i;
foo(a);
}
if (bar) {
int * a;
baz(a);
}
Этот код, скорее всего, будет иметь ожидаемый результат, потому что компилятор, вероятно, решит хранить обе переменные в одном и том же месте, поэтому второй a будет иметь последнее значение, которое имел другой a.
Встроенные функции могут иметь странное поведение, или вы как-то полагаетесь на то, что они не встроены (или иногда наоборот), что часто имеет место для неоптимизированного кода.
Вам определенно следует попробовать скомпилировать с предупреждениями, максимальными значениями которых являются (-Wall для gcc).
Это часто говорит вам о рискованном коде.
(редактировать)
Просто подумал о другом.
Если у вас есть несколько способов ссылки на переменную, у вас могут возникнуть проблемы, которые работают правильно без оптимизации, но выходят из строя при включении оптимизации. Это может произойти двумя способами.
Первое, если значение может быть изменено обработчиком сигнала или другим потоком. Вы должны сообщить об этом компилятору, чтобы он знал, что любой доступ предполагает, что значение необходимо перезагрузить и / или сохранить. Это делается с помощью ключевого слова volatile.
Второй псевдоним. Это когда вы создаете два разных способа доступа к одной и той же памяти. Компиляторы обычно быстро предполагают, что вы используете псевдонимы с указателями, но не всегда. Кроме того, они являются флагами оптимизации для некоторых из них, которые говорят им, что им не нужно быстро делать такие предположения, а также способами, которыми вы можете обмануть компилятор (сумасшедшие вещи, такие как while (foo != bar) { foo++; } *foo = x;
, явно не являющиеся копией bar to foo).