оптимизация рекурсии бесконечного хвоста

#include <iostream>

int foo(int i){
return foo(i + 1);
}

int main(int argc,char * argv[]){
if(argc != 2){
return 1;
}
std::cout << foo(std::atoi(argv[1])) << std::endl;
}

% clang ++ -O2 test.cc

% времени ./a.out 42

1490723512

./a.out 42 0.00s пользователь 0.00s система 69% процессор 0.004 всего

% времени ./a.out 42

1564058296

./a.out 42 0.00s пользователь 0.00s система 56% процессор 0.006 всего

% g ++ -O2 test.cc

% ./a.out 42 # реинкурсия infinte

^ C

% clang++ --version
clang version 3.3 (tags/RELEASE_33/final)
Target: x86_64-apple-darwin12.4.0
Thread model: posix
% g++ --version
i686-apple-darwin11-llvm-g++-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.11.00)
Copyright (C) 2007 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Так это ошибка или особенность clang ++?

1

Решение

Хотя и g ++, и clang ++ способны компилировать код C ++ 98 и C ++ 11, clang ++ изначально разрабатывался как компилятор C ++ 11 и имеет некоторые поведения C ++ 11, встроенные в его ДНК (так сказать) ,

В C ++ 11 стандарт C ++ стал ориентирован на потоки, а это означает, что теперь существует определенное поведение потоков. В частности, 1.10 / 24 гласит:

Реализация может предполагать, что любой поток в конечном итоге выполнит одно из следующих действий:

— прекратить,

— сделать вызов функции ввода-вывода библиотеки,

— получить доступ или изменить изменчивый объект, или

— выполнить операцию синхронизации или атомарную операцию.

[Примечание: это предназначено для разрешения преобразований компилятора, таких как удаление пустых циклов, даже если завершение не может быть доказано. — конец примечания]

И это именно то, что делает Clang ++ при оптимизации. Он видит, что функция не имеет побочных эффектов и удаляет ее даже если это не заканчивается.

7

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

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

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