2013-10-01 20 views
11

Generuje to Segmentation Fault: 11 i nie mam pojęcia, dlaczego.Usterka segmentacji Pythona?

Przed I dostać się do niego, oto kod:

import numpy.random as nprnd 
import heapq 
import sys 

sys.setrecursionlimit(10**6) 


def rlist(size, limit_low, limit_high): 
    for _ in xrange(size): 
     yield nprnd.randint(limit_low, limit_high) 

def iterator_mergesort(iterator, size): 
    return heapq.merge(
     iterator_mergesort(
      (iterator.__next__ for _ in xrange(size/2)), size/2), 
     iterator_mergesort(
      iterator, size - (size/2)) 
     ) 

def test(): 
    size = 10**3 
    randomiterator = rlist(size, 0, size) 
    sortediterator = iterator_mergesort(randomiterator, size) 
    assert sortediterator == sorted(randomiterator) 

if __name__ == '__main__': 
    test() 

Zasadniczo, to tylko mergesort który działa na iteratory i wyrażeń generatora zamiast pracować na listach, tak aby zminimalizować zużycie pamięci w jednym czasie . To nic specjalnego i wykorzystuje wbudowaną metodę heapq.merge() do scalania iteratorów, więc byłem bardzo zaskoczony, gdy wszystko się psuje.

Uruchomienie kodu szybko daje Segmentation Fault: 11 i okno błędu informujące mnie, że pyton się zawiesił. Nie mam pojęcia, gdzie szukać i jak debugować ten, więc każda pomoc będzie bardzo ceniona.

+0

Zwykle jedyne, kiedy dostaniesz segfault w pythonie, oznacza brak pamięci lub błąd w jednym z modułów C, z których korzystasz. [To pytanie] (http://stackoverflow.com/questions/10035541/what-causes-a-python-segmentation-fault) może ci się przydać. – rnorris

+0

Och, czuję się już całkiem głupio, zapomniałem przykleić podstawową skrzynkę do mojego mergesortu, więc zwiększenie limitu rekursji zrywa wszystko. – reem

+3

@sortfiend - Jeśli znalazłeś problem, powinieneś raczej napisać go jako [krótką odpowiedź i zaakceptować] (http://meta.stackoverflow.com/help/self-answer), zamiast edytować tytuł powiedz "RESOLVED". W ten sposób post ten będzie ładniej grał z algorytmami StackOverflow, a Ty możesz skończyć gromadząc kilka kolejnych uptów tu i tam :) – Michael0x2a

Odpowiedz

6

Segmentation Faults w Pythonie zdarzyć dla jednego z dwóch powodów:

zabraknie pamięci

Bug w module C

Tutaj usterka seg należący do pierwszego. Ty (I) masz bezkresową rekurencję, ponieważ nie ma podstawowego przypadku w iterator_mergesort(), będzie on wciąż wywoływał się sam na zawsze i na zawsze.

Zwykle pyton zgłasza wyjątek, który zakończy się przed wystąpieniem błędu segfault. Jednak limit rekursji został ustawiony bardzo wysoko, więc pytonowi zabrakło pamięci i zepsuje się zanim rozpozna, że ​​powinien wyrzucić wyjątek dla nieograniczonej rekursji.

Dodaj przypadek bazowy tak:

... 
def iterator_mergesort(iterator, size): 
return heapq.merge(
     iterator_mergesort(
      (iterator.next() for _ in xrange(size/2)), size/2), 
     iterator_mergesort(
      iterator, size - (size/2)) 
     ) if size >= 2 else iterator #<-- Specifically this 

Teraz przechodzi na funkcję i rodzaju test(), choć raczej powoli.