次のプログラムは、fun 2(MAXD + 1)回呼び出します。しかし、(私の考えが正しいなら)最大再帰深度は決してMAXDを超えてはなりません。コンパイルに時間がかかるかもしれませんが、RAMを食べるべきではありません。なぜこのconstexprコードはGCCにすべての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がすぐに3GB程度を割り当てた後にノートパソコンがスワップを開始します。私はまだそれにアクセスすることができないので、私はclang 3.1でそれを試していません。
これはGCCがテンプレートを使用する場合と同じように、関数呼び出しを賢明にしてメモを取ろうとしているということだけです。これがそうであれば、MRUキャッシュテーブルなどのサイズのように、どのくらいメモをしているのかに限界がないのは奇妙なことではありませんか?私はそれを無効にするスイッチが見つかりませんでした。
どうすればいいですか? 私は遺伝的プログラミングや何かのような高度なコンパイル時ライブラリを作るという考えを抱いています。コンパイラにはコンパイル時のテールコールの最適化がないので、ループには再帰が必要であると心配しています(必要な場合は少し醜いと思われる最大再帰深度パラメータを設定しても)それは無意味なスタックフレームで。したがって、私は深いスタックなしで任意に多くの関数呼び出しを取得するための上記の解決策を考え出しました。そのような機能は、折畳み/ループまたはトランポリングに使用できます。
EDIT: 今、私はclang 3.1で試してみましたが、どれくらい長く動作させても(つまりMAXDをどれくらい高くしても)メモリがまったくリークしません。 CPU使用率はほぼ100%で、メモリ使用率はほぼ0%です。おそらくこれはGCCのバグです。
私が確認しています関数ランタイムを実行し、長時間実行することができますが、RAMをまったく使用しないことを確認することで、スタックはMAXDを超えることはありません。 – Gurgeh
http://gcc.gnu.org/bugs/で推奨されているように報告する必要がありますか? – osgx
@osgxそれは本当にバグではありません。標準によると、彼らは私のRAMに好きなことをすることができると思います。また、私は彼らが何をしているかを知っている人(あなたが誰であるかを知っている;)が理由を教えてくれるようにしたい。 – Gurgeh