Quantcast

python segfault

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

python segfault

michael poeltl
hi,

can anybody tell why this 'little stupid *thing* of code' let's python-3.2.2, 2.6.X or python 2.7.2 segfault?

>> def get_steps2(pos=0, steps=0):
...     if steps == 0:
...         pos = random.randint(-1,1)
...     if pos == 0:
...         return steps
...     steps += 2
...     pos += random.randint(-1,1)
...     return get_steps2(pos,steps)
...
>>> import random, sys
>>> sys.setrecursionlimit(100000)
>>> for i in range(200):
...     print ( get_steps2() )
...
4
0
8
0
0
0
2
2
166
2
0
0
16
4
2
16
0
0
10
70
152
50
58
0
6
0
0
0
2
8
0
Segmentation fault
?>

funny, isn't it?
I was able to reproduce this segfault on various machines (32bit 64bit), ubuntu, slackware, debian
python.X segfaults on all of them

thx
Michael
--
Michael Poeltl
Computational Materials Physics      voice: +43-1-4277-51409
Univ. Wien, Sensengasse 8/12         fax:   +43-1-4277-9514 (or 9513)
A-1090 Wien, AUSTRIA   cmp.mpi.univie.ac.at
-------------------------------------------------------------------------------
ubuntu-11.10 | vim-7.3 | python-3.2.2 | mutt-1.5.21 | elinks-0.12
-------------------------------------------------------------------------------
--
http://mail.python.org/mailman/listinfo/python-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: python segfault

Chris Kaynor
On Tue, Mar 27, 2012 at 3:27 PM, Michael Poeltl
<[hidden email]> wrote:

> hi,
>
> can anybody tell why this 'little stupid *thing* of code' let's python-3.2.2, 2.6.X or python 2.7.2 segfault?
>
>>> def get_steps2(pos=0, steps=0):
> ...     if steps == 0:
> ...         pos = random.randint(-1,1)
> ...     if pos == 0:
> ...         return steps
> ...     steps += 2
> ...     pos += random.randint(-1,1)
> ...     return get_steps2(pos,steps)
> ...
>>>> import random, sys
>>>> sys.setrecursionlimit(100000)

If you remove this setrecursionlimit, it will throw an exception. The
issue is that your code is overflowing the C stack by trying to make
too many calls. The Python recursion limit prevents this by turning
such cases into Python exceptions prior to the stack overflow.

As your recursion is based on a random number generator, all you need
is a sequence of random numbers that is unbalanced between -1 and 1
results for 1000-3000 calls (the exact number will vary from os,
compiler, maybe machine, etc), which is not too unlikely to occur.
--
http://mail.python.org/mailman/listinfo/python-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: python segfault

Christian Heimes-2
In reply to this post by michael poeltl
Am 28.03.2012 00:27, schrieb Michael Poeltl:
> hi,
>
> can anybody tell why this 'little stupid *thing* of code' let's python-3.2.2, 2.6.X or python 2.7.2 segfault?

The code segfaults because you have increased the recursion limit. The
amount of recursions is limited by the stack size. A C program with a
usually stack size can have about 4000 recursions. Python takes at least
two stack levels for each recursion.

The documentation
http://docs.python.org/library/sys.html#sys.setrecursionlimit contains a
warning, too.

Christian

--
http://mail.python.org/mailman/listinfo/python-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: python segfault

Dave Angel-3
In reply to this post by michael poeltl
On 03/27/2012 06:27 PM, Michael Poeltl wrote:

> hi,
>
> can anybody tell why this 'little stupid *thing* of code' let's python-3.2.2, 2.6.X or python 2.7.2 segfault?
>
>>> def get_steps2(pos=0, steps=0):
> ...     if steps == 0:
> ...         pos = random.randint(-1,1)
> ...     if pos == 0:
> ...         return steps
> ...     steps += 2
> ...     pos += random.randint(-1,1)
> ...     return get_steps2(pos,steps)
> ...
> <SNIP>
> 0
> 2
> 8
> 0
> Segmentation fault
> ?>
>
> funny, isn't it?
> I was able to reproduce this segfault on various machines (32bit 64bit), ubuntu, slackware, debian
> python.X segfaults on all of them
>
> thx
> Michael

Others have explained why you can't just raise the recursion limit to
arbitrarily large values, and why there's no particular bound on the
possible recursion size.  But the real question is why you don't do the
completely trivial conversion to a non-recursive equivalent.

All you need do is add a while True:  to the beginning of the function,
and remove the return statement.



--

DaveA

--
http://mail.python.org/mailman/listinfo/python-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: python segfault

michael poeltl
hi,

* Dave Angel <[hidden email]> [2012-03-28 04:38]:

> On 03/27/2012 06:27 PM, Michael Poeltl wrote:
> >hi,
> >
> >can anybody tell why this 'little stupid *thing* of code' let's python-3.2.2, 2.6.X or python 2.7.2 segfault?
> >
> >>>def get_steps2(pos=0, steps=0):
> >...     if steps == 0:
> >...         pos = random.randint(-1,1)
> >...     if pos == 0:
> >...         return steps
> >...     steps += 2
> >...     pos += random.randint(-1,1)
> >...     return get_steps2(pos,steps)
> >...
> ><SNIP>
> >0
> >2
> >8
> >0
> >Segmentation fault
> >?>
> >
> >funny, isn't it?
> >I was able to reproduce this segfault on various machines (32bit 64bit), ubuntu, slackware, debian
> >python.X segfaults on all of them
> >
> >thx
> >Michael
>
> Others have explained why you can't just raise the recursion limit
> to arbitrarily large values, and why there's no particular bound on
> the possible recursion size.  But the real question is why you don't
> do the completely trivial conversion to a non-recursive equivalent.
>
> All you need do is add a while True:  to the beginning of the
> function, and remove the return statement.
yeah - of course 'while True' was the first, most obvious best way... ;-)
but I was asked if there was a way without 'while True'
and so I started the 'recursive function'

and quick quick; RuntimeError-Exception -> not thinking much -> just adding
two zeros to the default limit (quick and dirty) -> segfault ==> subject: python segfault ;-)

and that was my first time that I received a segfault and not an Exception

NOW it's quite clear ;-)

thank you!
Michael
>
>
>
> --
>
> DaveA
>

--
Michael Poeltl
Computational Materials Physics      voice: +43-1-4277-51409
Univ. Wien, Sensengasse 8/12         fax:   +43-1-4277-9514 (or 9513)
A-1090 Wien, AUSTRIA   cmp.mpi.univie.ac.at
-------------------------------------------------------------------------------
ubuntu-11.10 | vim-7.3 | python-3.2.2 | mutt-1.5.21 | elinks-0.12
-------------------------------------------------------------------------------
--
http://mail.python.org/mailman/listinfo/python-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: python segfault

Kiuhnm
In reply to this post by Dave Angel-3
On 3/28/2012 8:16, Michael Poeltl wrote:
> yeah - of course 'while True' was the first, most obvious best way... ;-)
> but I was asked if there was a way without 'while True'
> and so I started the 'recursive function'
>
> and quick quick; RuntimeError-Exception ->  not thinking much ->  just adding
> two zeros to the default limit (quick and dirty) ->  segfault ==>  subject: python segfault ;-)

You give up too easily! Here's another way:

--->
def get_steps2(pos=0, steps=0, level = 100):
     if steps == 0:
         pos = random.randint(-1,1)
     if pos == 0:
         return steps
     steps += 2
     pos += random.randint(-1,1)

     if level == 0:
         return (pos, steps)
     res = get_steps2(pos,steps, level-1)
     if not isinstance(res, tuple):
         return res
     return get_steps2(res[0], res[1], level-1)

import random
for i in range(200):
     print ( get_steps2() )

print("done")
input("")
<---

Now the limit is 1267650600228229401496703205376. I hope that's enough.

Kiuhnm
--
http://mail.python.org/mailman/listinfo/python-list
Loading...