|
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 |
|
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 |
|
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 |
|
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 |
|
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. 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 |
|
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 |
| Powered by Nabble | Edit this page |
