2013-10-01 26 views
11

Questo genera un Segmentation Fault: 11 e non ho idea del perché.Un errore di segmentazione Python?

Prima di entrare in esso, ecco il codice:

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() 

In sostanza, è solo un Mergesort che funziona su iteratori e le espressioni del generatore invece di lavorare su liste in modo da ridurre al minimo l'occupazione di memoria in qualsiasi momento . Non è niente di speciale, e usa il metodo built-in heapq.merge() per unire gli iteratori, quindi sono rimasto piuttosto sorpreso quando tutto si è rotto.

L'esecuzione rapida del codice fornisce Segmentation Fault: 11 e una finestra di errore che indica che Python si è arrestato in modo anomalo. Non ho idea di dove guardare o come eseguire il debug di questo, quindi qualsiasi aiuto sarebbe molto apprezzato.

+0

In genere, le uniche volte che si ottiene un segfault in python è quando si esaurisce la memoria o si verifica un errore in uno dei moduli C che si sta utilizzando. [Questa domanda] (http://stackoverflow.com/questions/10035541/what-causes-a-python-segmentation-fault) potrebbe esserti utile. – rnorris

+0

Oh, ora mi sento un po 'stupido, ho dimenticato di inserire un caso base nel mio insieme, quindi aumentare il limite di ricorsione rompe tutto. – reem

+3

@sortfiend - Se hai trovato il problema, dovresti probabilmente scriverlo come [risposta breve e accettarlo] (http://meta.stackoverflow.com/help/self-answer), piuttosto che modificare il titolo in dì "RISOLTO". In questo modo, questo post giocherà meglio con gli algoritmi di StackOverflow e potresti finire per accumulare un po 'più di uptotes qua e là :) – Michael0x2a

risposta

6

Segmentation Faults in python verificarsi per uno dei due motivi:

Si esegue fuori la memoria

Bug in un modulo C

Qui, la colpa seg appartiene alla prima. Tu (I) hai una ricorsione sconfinata perché non esiste un caso base in iterator_mergesort(), continuerà a chiamarsi su se stessa per sempre.

In genere Python genera un'eccezione e termina prima di causare un segfault. Tuttavia, il limite di ricorsione è stato impostato estremamente alto, quindi Python esaurisce la memoria e si interrompe prima che riconosca che dovrebbe generare un'eccezione per una ricorsione illimitata.

Aggiungi un caso base in questo modo:

... 
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 

Ora passa la funzione di test() e le specie, anche se piuttosto lentamente.