Как правильно указывает N1509, текущий черновик по существу дает неопределенное поведениебесконечные циклы в 6.8.5p6.Основной проблемой для этого является то, что он позволяет коду перемещаться по потенциально не завершающемуся циклу.Например, предположим, что у нас есть следующие циклы, где count и count2 - глобальные переменные (или у них был взят их адрес), а p - локальная переменная, адрес которой не был взят:
for (p = q; p != 0; p = p -> next) {
++count;
}
for (p = q; p != 0; p = p -> next) {
++count2;
}
Couldэти два цикла объединяются и заменяются следующим циклом?
for (p = q; p != 0; p = p -> next) {
++count;
++count2;
}
Без специального разрешения в 6.8.5p6 для бесконечных циклов это будет запрещено: если первый цикл не завершается, поскольку q указывает накруговой список, оригинал никогда не пишет в count2.Таким образом, он может быть запущен параллельно с другим потоком, который обращается или обновляет count2.Это больше не безопасно с преобразованной версией, которая делает доступ к count2, несмотря на бесконечный цикл.Таким образом, преобразование потенциально представляет гонку данных.
В подобных случаях очень маловероятно, что компилятор сможет доказать завершение цикла;он должен понимать, что q указывает на ациклический список, который, как я считаю, находится за пределами возможностей большинства основных компиляторов и часто невозможен без всей информации о программе.
Ограничения, накладываемые бесконечными циклами, являются ограничениемоб оптимизации завершающих циклов, для которых компилятор не может доказать завершение, а также об оптимизации фактически не заканчивающихся циклов.Первые гораздо чаще встречаются, чем вторые, и их часто интереснее оптимизировать.
Существуют также явные циклы for с целочисленной переменной цикла, в которых компилятору будет трудно доказать завершение, и этоТаким образом, компилятору будет трудно реструктурировать циклы без 6.8.5p6.Даже что-то вроде
for (i = 1; i != 15; i += 2)
или
for (i = 1; i <= 10; i += j)
кажется нетривиальным в обращении.(В первом случае для доказательства завершения требуется некоторая базовая теория чисел, во втором случае нам нужно что-то знать о возможных значениях j, чтобы сделать это. Обтекание целых чисел без знака может усложнить некоторые из этих рассуждений.)
Эта проблема, по-видимому, относится почти ко всем преобразованиям реструктуризации цикла, включая преобразования распараллеливания компилятора и оптимизации кэша, оба из которых, вероятно, приобретут важность и уже часто важны для числового кода.Похоже, это может обернуться существенными затратами для возможности писать бесконечные циклы наиболее естественным из возможных способов, тем более что большинство из нас редко пишут намеренно бесконечные циклы.