2013-10-01 2 views
11

Это генерирует Segmentation Fault: 11, и я не знаю, почему.Ошибка сегментации Python?

Перед тем, как попасть в него, вот код:

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

В принципе, это просто слияние, которая работает на итераторы и выражениях генератора вместо работе над списками, чтобы минимизировать объем памяти в любой момент времени , Это ничего особенного и использует встроенный метод heapq.merge() для слияния итераторов, поэтому я был очень удивлен, когда все ломается.

Запуск кода быстро дает Segmentation Fault: 11 и окно с сообщением о том, что python разбился. Я понятия не имею, где искать или как отлаживать этот, так что любая помощь будет высоко оценена.

+0

Как правило, единственное, что вы получите segfault в python, - это когда вы потеряли память или есть ошибка в одном из модулей C, которые вы используете. [Этот вопрос] (http://stackoverflow.com/questions/10035541/what-causes-a-python-segmentation-fault) может быть вам полезен. – rnorris

+0

О, теперь я чувствую себя совсем немой, я забыл приклеить базовый футляр в моем слиянии, поэтому увеличение предела рекурсии ломает все. – reem

+3

@sortfiend - Если вы обнаружили проблему, вы должны, вероятно, написать ее как [короткий ответ и принять его] (http://meta.stackoverflow.com/help/self-answer), а не редактировать заголовок скажем «ПОСТАНОВИЛИ». Таким образом, этот пост будет играть лучше с алгоритмами StackOverflow, и вы можете в конечном итоге накапливать еще несколько оборотов здесь и там :) – Michael0x2a

ответ

6

Segmentation Faults в питоне произойти по одной из двух причин:

Вы бежите из памяти

Ошибка в модуле C

Здесь вина сегментной принадлежит к первому. У вас (я) есть безграничная рекурсия, потому что в iterator_mergesort() нет базового аргумента, он будет постоянно называть себя навсегда.

Как правило, python генерирует исключение для этого, и оно завершается перед вызовом segfault. Тем не менее, предел рекурсии был установлен чрезвычайно высоким, поэтому у python заканчивается память и ломается, прежде чем он распознает, что он должен генерировать исключение для неограниченной рекурсии.

Добавить базовый вариант, как так:

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

Теперь она проходит функцию тест() и виды, хотя и довольно медленно.

Смежные вопросы