次のプログラムはfun を2 ^ (MAXD + 1) 回呼び出します。ただし、最大再帰深度が MAXD を超えることはありません (私の考えが正しければ)。したがって、コンパイルに時間がかかる場合がありますが、RAM を消費することはありません。
#include<iostream>
const int MAXD = 20;
constexpr int fun(int x, int depth=0){
return depth == MAXD ? x : fun(fun(x + 1, depth + 1) + 1, depth + 1);
}
int main(){
constexpr int i = fun(1);
std::cout << i << std::endl;
}
問題は、RAM を消費することがまさにそれであるということです。MAXD を 30 まで上げると、GCC 4.7.2 が 3 GB 程度をすばやく割り当てた後、ラップトップがスワップし始めます。現在、clang 3.1 にアクセスできないため、clang 3.1 ではまだ試していません。
私の唯一の推測は、これは GCC が巧妙になりすぎて、テンプレートの場合のように関数呼び出しをメモ化しようとすることに関係があるということです。だとすると、MRU キャッシュ テーブルのサイズとか、メモ化の量に制限がないのはおかしいと思いませんか? 無効にするスイッチが見つかりませんでした。
なぜ私はこれをするのですか?私は、遺伝的プログラミングなどの高度なコンパイル時ライブラリを作成するというアイデアをいじっています。コンパイラにはコンパイル時の末尾呼び出しの最適化がないため、ループするものすべてに再帰が必要になるのではないかと心配しています (最大再帰深度パラメータを上げても、要求するのが少し醜いように見えます) すべての RAM がすぐに割り当てられていっぱいになります無意味なスタックフレームでそれ。したがって、深いスタックなしで任意に多くの関数呼び出しを取得するための上記のソリューションを思いつきました。このような機能は、折りたたみ/ループまたはトランポリンに使用できます。
編集:clang 3.1で試してみましたが、どれだけ長く機能させても(つまり、MAXDをどれだけ高くしても)メモリリークはまったくありません。予想通り、CPU 使用率はほぼ 100%、メモリ使用率はほぼ 0% です。おそらく、これは GCC の単なるバグです。