SharpC: A C Interpreter In C# - 1101

如果运行以下包含于多次递归调用的测试C代码:

...
void fork2(int a, int b)
{
    if ((a + b) % 1024 == 0)
        print("iterate fork2: a=%i, b=%i\n", a, b);
    
    if (a + b == 2)
        return;
    else
        fork2(--a, --b);
}

...

void main()
{
    ...
    fork2(65535, 65535);
    ...
}

将会导致StackOverflowException错误。这是由于默认堆栈大小为1M,很快就会耗尽。
解决办法:

  1. 使用循环替代递归。
  2. 使用较小次数的递归。
  3. 修改SharpC,使之能够胜任。

显然1,2不在考虑之列。
可以对SharpC做以下修改:
先设定一个大的堆栈尺寸,在SharpC中:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Diagnostics;

namespace SharpC
{
    using Grammar;

    public class SharpC
    {
        // Static
        static public int MaxStackSize = 1024 * 1024 * 512;  //开个512M的堆栈
        ...

因为无法设置程序的堆栈,只能另开一个线程:

namespace SharpC
{
    using Grammar;

    public class SharpC
    {

        ....
public void Run(bool forceReparsing = false)
        {
            if (!m_lastParsingResult || forceReparsing)
                Parse();

            if (m_context != null)
            {
                if (OnBeforeRun != null)
                    OnBeforeRun(this, m_context);

                (new System.Threading.Thread(delegate() {
                        
                        try
                        {
                            IsRunning = true;
                            m_context.Run(m_context);
                        }
                        finally
                        {
                            IsRunning = false;

                            if (OnAfterRun != null)
                                OnAfterRun(this, m_context);
                        }
                }, MaxStackSize)).Start();
            }
        }

        ....

另外,FunctionDefine.cs中的保存和恢复参数的做法是错误的,正确的方法是:注释掉它们!

namespace SharpC.Grammar.Function
{
    public class FunctionDefine : Context
    {
        ...
        private void BeforeRun(Context ctx, List parameters)
        {
            if (IsFirstRunning)
            {
                ConfigReturnEvent(ctx);

                AllocateFixedArguments(ctx);
                
                IsFirstRunning = false;
            }

            if (IsVariableArgument)
            {
                FreeVariableArgument(ctx);

                AllocateVariableArguments(ctx, parameters);
            }

            //SavePreviousParameters(ctx);

            InitArguments(ctx, parameters);

            IteratorCount++;
        }
        ....

private void AfterRun(Context ctx)
        {
            IteratorCount--;

            if (IteratorCount > 0)
            {
                /*
                if (m_parameterStack.Count > 0)
                {
                    RestoreParameter(ctx);
                }
                */
            }
            else
            {
                // Clean variable arguments
                if (IsVariableArgument)
                {
                    FreeVariableArgument(ctx);
                }
            }
        }

       ...

现在可以进行深层递归了。
继续运行测试代码,递归65535次,每512次输出一次递归的结果。运行结果如下:
运行结果:

你可能感兴趣的:(c,c#)