Thread overview
Segfault games with factorials
Jul 24, 2014
Darren
Jul 24, 2014
H. S. Teoh
Jul 24, 2014
Darren
Jul 24, 2014
John Colvin
Jul 24, 2014
safety0ff
July 24, 2014
I have the following code in fac.d (modified from the factorial examples on RosettaCode):

#!/usr/bin/rdmd
import std.bigint;

pure BigInt factorial(BigInt n) {
    static pure BigInt inner(BigInt n, BigInt acc) {
    	return n == 0 ? acc : inner(n - 1, acc * n);
    }
    return inner(n, BigInt("1"));
}

void main(string[] args) {
	import std.stdio;
	BigInt input = args[1];
	writeln(factorial(input));
	return;
}

It (more or less consistently) on my machine will calculate 'fac 47610', and (more or less consistently) will core dump with a segfault on 'fac 47611'.

Interestingly, if I redirect stdout to a file it will usually manage to get to 47612.

To satisfy my own curiosity about what's happening, are there any resources I can use to analyse the core dump?

Thanks.
July 24, 2014
On Thu, Jul 24, 2014 at 01:14:40PM +0000, Darren via Digitalmars-d-learn wrote:
> I have the following code in fac.d (modified from the factorial
> examples on RosettaCode):
> 
> #!/usr/bin/rdmd
> import std.bigint;
> 
> pure BigInt factorial(BigInt n) {
>     static pure BigInt inner(BigInt n, BigInt acc) {
>     	return n == 0 ? acc : inner(n - 1, acc * n);
>     }
>     return inner(n, BigInt("1"));
> }
> 
> void main(string[] args) {
> 	import std.stdio;
> 	BigInt input = args[1];
> 	writeln(factorial(input));
> 	return;
> }
> 
> It (more or less consistently) on my machine will calculate 'fac
> 47610', and (more or less consistently) will core dump with a segfault
> on 'fac 47611'.
[...]

You're probably running out of stack space because of your recursive function. Write it as a loop instead, and you should be able to go farther:

	pure BigInt factorial(BigInt n) {
		auto result = BigInt(1);
		while (n > 1)
			result *= n;
		return result;
	}


T

-- 
Ignorance is bliss... until you suffer the consequences!
July 24, 2014
On Thursday, 24 July 2014 at 14:39:12 UTC, H. S. Teoh via Digitalmars-d-learn wrote:
> On Thu, Jul 24, 2014 at 01:14:40PM +0000, Darren via Digitalmars-d-learn wrote:
>> I have the following code in fac.d (modified from the factorial
>> examples on RosettaCode):
>> 
>> #!/usr/bin/rdmd
>> import std.bigint;
>> 
>> pure BigInt factorial(BigInt n) {
>>     static pure BigInt inner(BigInt n, BigInt acc) {
>>     	return n == 0 ? acc : inner(n - 1, acc * n);
>>     }
>>     return inner(n, BigInt("1"));
>> }
>> 
>> void main(string[] args) {
>> 	import std.stdio;
>> 	BigInt input = args[1];
>> 	writeln(factorial(input));
>> 	return;
>> }
>> 
>> It (more or less consistently) on my machine will calculate 'fac
>> 47610', and (more or less consistently) will core dump with a segfault
>> on 'fac 47611'.
> [...]
>
> You're probably running out of stack space because of your recursive
> function. Write it as a loop instead, and you should be able to go
> farther:
>
> 	pure BigInt factorial(BigInt n) {
> 		auto result = BigInt(1);
> 		while (n > 1)
> 			result *= n;
> 		return result;
> 	}
>
>
> T

It does seem that's the case. Which is odd, as I thought that DMD and LDC did TCO. Not in this case obviously.

PS. This was a slightly silly program, but in the general case, is there a way to use a core dump to diagnose a stack overflow?
July 24, 2014
On Thursday, 24 July 2014 at 14:59:16 UTC, Darren wrote:
> On Thursday, 24 July 2014 at 14:39:12 UTC, H. S. Teoh via Digitalmars-d-learn wrote:
>> On Thu, Jul 24, 2014 at 01:14:40PM +0000, Darren via Digitalmars-d-learn wrote:
>>> I have the following code in fac.d (modified from the factorial
>>> examples on RosettaCode):
>>> 
>>> #!/usr/bin/rdmd
>>> import std.bigint;
>>> 
>>> pure BigInt factorial(BigInt n) {
>>>    static pure BigInt inner(BigInt n, BigInt acc) {
>>>    	return n == 0 ? acc : inner(n - 1, acc * n);
>>>    }
>>>    return inner(n, BigInt("1"));
>>> }
>>> 
>>> void main(string[] args) {
>>> 	import std.stdio;
>>> 	BigInt input = args[1];
>>> 	writeln(factorial(input));
>>> 	return;
>>> }
>>> 
>>> It (more or less consistently) on my machine will calculate 'fac
>>> 47610', and (more or less consistently) will core dump with a segfault
>>> on 'fac 47611'.
>> [...]
>>
>> You're probably running out of stack space because of your recursive
>> function. Write it as a loop instead, and you should be able to go
>> farther:
>>
>> 	pure BigInt factorial(BigInt n) {
>> 		auto result = BigInt(1);
>> 		while (n > 1)
>> 			result *= n;
>> 		return result;
>> 	}
>>
>>
>> T
>
> It does seem that's the case. Which is odd, as I thought that DMD and LDC did TCO. Not in this case obviously.
>
> PS. This was a slightly silly program, but in the general case, is there a way to use a core dump to diagnose a stack overflow?

A debugger should be able to tell you why the segfault occurred.
July 24, 2014
On Thursday, 24 July 2014 at 14:59:16 UTC, Darren wrote:
>
> It does seem that's the case. Which is odd, as I thought that DMD and LDC did TCO. Not in this case obviously.

DMD doesn't do it with the :? operator: https://issues.dlang.org/show_bug.cgi?id=3713