1

I'm completing a pretty easy programming excersize with the following code:

    using System;

    namespace Factorial

{
    class MainClass
    {

        static int fives(int x) {

            int r = 0;
            while(x % 5 == 0) {
                r++;
                x /= 5;
            }
            return r;

        }

        static int z(int x) {

            if (x == 1)
                return 0;
            else
                return z (x-1) + fives (x);

        }

        public static void Main (string[] args)
        {
            int testCases = Convert.ToInt32 (Console.ReadLine ());
            int[] xs = new int[testCases];
            for (int i=0; i<testCases; i++)
                xs [i] = Convert.ToInt32 (Console.ReadLine ());
            foreach (int x in xs)
                Console.WriteLine (z (x));
        }
    }
}

It seems to work OK with small numbers, but with 8735373 from the example it prints "Segmentation fault: 11". Does it mean that I run out of memory because of recursion going in too deep? What causes it?

(I run C# in Mono 2.10.8 on a Mac.)

P.S.: If anyone's interested in the excersize itself, here's my final solution (much more optimized).

Matt
  • 74,352
  • 26
  • 153
  • 180
Max Yankov
  • 12,551
  • 12
  • 67
  • 135

4 Answers4

4

That looks like an unhandled StackOverflowException - common when overusing recursion. So... don't overuse recursion. It might be fine for maths and some very specific languages (F# would probably cope), but C#... not so much.

That looks like (not verified):

    static int z(int x)
    {
        int accumulator = 0;
        while(x!=1)
        {
            accumulator += fives(x);
            x--;
        }
        return accumulator;
    }

which doesn't error - it doesn't recurse (although it does call fives per iteration). Even better: do the algebra to find the direct formula.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
2

When you use the larger number your recursion steps is causing StackOverflowException and if you look into the debugger you will see after how many recursive steps the exception occurred.

I think Mono code somehow consider stackoverflow exception to Segmentaiton fault which could be how it is handled.

enter image description here

You could debug it if you wish: How do I debug a segmentation fault in Mono on Ubuntu without any debugger?

Community
  • 1
  • 1
AvkashChauhan
  • 20,495
  • 3
  • 34
  • 65
1

It seems that simple conversion from recursion to loop solved the problem:

    static int z (int x)
    {
        int result = 0;
        for (int i=1; i<=x; i++) {
            result += fives (i);
        }
        return result;
    }
Max Yankov
  • 12,551
  • 12
  • 67
  • 135
  • sure you don't want to start with `i=2` ? – Marc Gravell May 29 '12 at 21:54
  • I'm mainly worried about the special case of `1` when translating `z`. If your `i=5` relates to further analysis of `fives(...)`, then that is separate: the first job is to translate `z` correctly, and *you haven't done that*. It is executing `fives(1)`, which the old version ***did not***. – Marc Gravell May 29 '12 at 21:57
1

If the issue was caused by the large amount of recursion, the error would probably be a StackOverflowException. As golergka, previously stated, I'm pretty sure it's a Mono fault. A segmentation fault occurs arises when memory is being mismanaged by trying to reach memory addresses that should not be reached. This type of error is a system error... not a C# exception. I'm almost sure that Mono isn't managing memory very well with large numbers. I hope that helps you in your research.

razorsyntax
  • 339
  • 3
  • 8
  • 42