これはほんのわずかかもしれません。
コルーチンライブラリを使用します。これで、自分のスタックをヒープから割り当てます。呼び出しスタック内の深さを追跡するためにコードを再構築し、危険なほど深くなったら新しいCothreadを作成し、その代わりにそのコードに切り替えます。ヒープメモリが足りなくなると、古いコードをフリーズしてメモリを解放します。もちろん、あなたは同じアドレスにそれらを解凍することをお勧めします - あなたが制御することができるあなた自身の競技場の自分自身のスタックを割り当てることをお勧めします。実際には、Cothreadスタックのために同じメモリを再利用し、一度に1つずつメモリを交換する方が簡単かもしれません。
アルゴリズムを再帰的でないものに書き換えることは間違いありません。
これは働いて、それの一例であってもよいし、それだけで事故に正しい答えを印刷することがあります。
#include <stdio.h>
#include "libco.h"
//byuu's libco has been modified to use a provided stack; it's a simple mod, but needs to be done per platform
//x86.c:
////if(handle = (cothread_t)malloc(size)) {
//handle = (cothread_t)stack;
//here we're going to have a stack on disk and have one recursion's stack in RAM at a time
//I think it may be impossible to do this without a main thread controlling the coroutines, but I'm not sure.
#define STACKSIZE (32*1024)
char stack[STACKSIZE];
FILE* fpInfiniteStack;
cothread_t co_mothership;
#define RECURSING 0
#define EXITING 1
int disposition;
volatile int recurse_level;
int call_in_cothread(int (*entrypoint)(int), int arg);
int fibo_b(int n);
int fibo(int n)
{
if(n==0)
return 0;
else if(n==1)
return 1;
else {
int a = call_in_cothread(fibo,n-1);
int b = call_in_cothread(fibo_b,n-2);
return a+b;
}
}
int fibo_b(int n) { printf("fibo_b\n"); return fibo(n); } //just to make sure we can call more than one function
long filesize;
void freeze()
{
fwrite(stack,1,STACKSIZE,fpInfiniteStack);
fflush(fpInfiniteStack);
filesize += STACKSIZE;
}
void unfreeze()
{
fseek(fpInfiniteStack,filesize-STACKSIZE,SEEK_SET);
int read = fread(stack,1,STACKSIZE,fpInfiniteStack);
filesize -= STACKSIZE;
fseek(fpInfiniteStack,filesize,SEEK_SET);
}
struct
{
int (*proc)(int);
int arg;
} thunk, todo;
void cothunk()
{
thunk.arg = thunk.proc(thunk.arg);
disposition = EXITING;
co_switch(co_mothership);
}
int call_in_cothread(int (*proc)(int), int arg)
{
if(co_active() != co_mothership)
{
todo.proc = proc;
todo.arg = arg;
disposition = RECURSING;
co_switch(co_mothership);
//we land here after unfreezing. the work we wanted to do has already been done.
return thunk.arg;
}
NEXT_RECURSE:
thunk.proc = proc;
thunk.arg = arg;
cothread_t co = co_create(stack,STACKSIZE,cothunk);
recurse_level++;
NEXT_EXIT:
co_switch(co);
if(disposition == RECURSING)
{
freeze();
proc = todo.proc;
arg = todo.arg;
goto NEXT_RECURSE;
}
else
{
recurse_level--;
unfreeze();
if(recurse_level==0)
return thunk.arg; //return from initial level of recurstion
goto NEXT_EXIT;
}
return -666; //this should not be possible
}
int main(int argc, char**argv)
{
fpInfiniteStack = fopen("infinite.stack","w+b");
co_mothership = co_active();
printf("result: %d\n",call_in_cothread(fibo,10));
}
は今、あなたは、単に利用可能ですどのくらいの、どのくらいのメモリのシステムで検出する必要がありますコールスタックの大きさ、およびコールスタックが使い尽くされたときに、無限スタックをいつ展開するかを知ることができます。 1つのシステムには簡単なものではありません。スタックが実際にどのように戦う代わりに使用されるのかを知る方が良いでしょう。
いいえ、不可能です。再帰なしで書き換えます。 – molbdnilo
反復を反復に回し、問題を解決しました。 –
また、コールスタックを「クラウド」に拡張することもできません。 – molbdnilo