Сбой реализации итеративной сортировки слиянием на С++ при больших размерах ввода из-за переполнения стека

У меня нет большого опыта работы с переполнением стека, я думал, что они были вызваны рекурсивными функциями, превышающими определенную глубину рекурсии, почему они возникают здесь, в этой итеративной реализации сортировки слиянием!

    #include<iostream>
    #include <stdlib.h>
    #define SIZE 3000000

    int L[2500002];
    int R[2500002];

    using namespace std;

    int min(int a, int b) {
        return !(b<a) ? a : b;
    }

    void Merge(int data[], int p, int q, int r)
    {
        if (q >= SIZE)q = (r + p) / 2;
        int sizeL = q - p + 2;
        int sizeR = r - q + 1;

        for (int i = 0; i < sizeL - 1; i++)
            L[i] = data[i + p];
        for (int i = 0; i < sizeR - 1; i++)
            R[i] = data[i + q + 1];

        int max;
        if (L[sizeL - 2]>R[sizeR - 2])
            max = L[sizeL - 2] + 1;
        else
            max = R[sizeR - 2] + 1;
        L[sizeL - 1] = R[sizeR - 1] = max;

        int indexL = 0, indexR = 0;
        for (int i = p; i <= r; i++){
            if (L[indexL] <= R[indexR]){
                data[i] = L[indexL];
                indexL++;
            }
            else{
                data[i] = R[indexR];
                indexR++;
            }
        }


    }

    void MergeSort(int data[], int p, int r)
    {
        for (int i = 1; i< SIZE; i *= 2)
            for (int j = 0; j < SIZE; j += 2 * i)
                Merge(data, j, j + i - 1, min((j + 2 * i - 1), SIZE - 1));
    }
    /*****************************************************************************/

    bool IsSorted(int data[], int size)
    {
        int i;

        for (i = 0; i<(size - 1); i++)
        {
            if (data[i] > data[i + 1])
                return false;
        }
        return true;
    }

    int main()
    {
        int data[SIZE];
        for (int i = 0; i < SIZE; i++)
            data[i] = rand();
        MergeSort(data,0,SIZE-1);
        if(IsSorted(data, SIZE))
            cout << "Sorted correctly";
        else
            cout << "incorrect sorting";
        getchar();
        return 0;
    }

person user2968505    schedule 04.04.2014    source источник
comment
просто предположение, из памяти? 4194305/1024 = 4096,00097656. У тебя 4гб оперативки?   -  person fonZ    schedule 04.04.2014
comment
4194304 это ровно 4 Гб. Может быть, это звонит в колокол. Просто предположение.   -  person Jabberwocky    schedule 04.04.2014
comment
Но рекурсивная версия использует тот же объем памяти, поэтому я не понимаю, как это может быть.   -  person user2968505    schedule 04.04.2014
comment
Пожалуйста, разместите код в самом вопросе. Также создайте пример программы с только тем, что необходимо - нет смысла иметь функции для быстрой сортировки, сортировки вставками или чтения из ввода (например, входные данные могут быть жестко закодированы).   -  person Bernhard Barker    schedule 04.04.2014
comment
@Dukeling оп опубликовал код. И как вы предлагаете выкладывать конкретную часть кода, не зная, где ошибка? Оп четко заявил, что это так.   -  person fonZ    schedule 04.04.2014
comment
@fonZ ДА, он обязательно должен заниматься отладкой самостоятельно. Каждый программист должен как минимум уметь выяснить, где возникает ошибка. Публиковать 400 строк кода без какой-либо попытки свести его к проблемной части — пустая трата времени.   -  person Niklas B.    schedule 04.04.2014
comment
@fonZ OP опубликовал код, но не в самом вопросе - зависимость сообщений от внешних ресурсов не соответствует попытке иметь Stack Overflow может стать долговременной автономной базой знаний. OP уже знает, что проблема связана с сортировкой слиянием, поэтому я не вижу абсолютно никаких причин, по которым следует включать код для быстрой сортировки или сортировки вставками - аналогично, большую часть другого кода, вероятно, также можно удалить. Замена чтения ввода на жесткое кодирование его генерации также является незначительным изменением, уменьшающим объем кода и позволяющим любому протестировать его практически без усилий.   -  person Bernhard Barker    schedule 04.04.2014
comment
@fonZ: Может быть, я запутался, но почему вы думаете, что для 4194305 int требуется 4 ГБ ОЗУ? Если вы посмотрите на связанный код, я вижу только четыре глобальных массива int, которые занимают около 80 МБ.   -  person Blastfurnace    schedule 04.04.2014
comment
@MichaelWalz 4194304 не 4 ГБ; это чуть больше 4 млн.   -  person nobody    schedule 04.04.2014
comment
@Dukeling Извините, я так долго не отвечал, но мне пришлось немного уйти, в любом случае я отредактировал код, относящийся к проблеме.   -  person user2968505    schedule 04.04.2014
comment
Ваш текущий код, вероятно, дает сбой, потому что вы пытаетесь определить массив из 3000000 int внутри main(). Это слишком много для автоматического хранения (стека).   -  person Blastfurnace    schedule 04.04.2014
comment
Вы правы, я должен был сделать его глобальным, я думал, что эта проблема переполнения стека будет связана с моим исходным кодом, но ее нет в оригинале, она уже была определена как глобальная, но моя итеративная сортировка слиянием дает сбой после определенного размера ввода , в то время как моя быстрая сортировка и рекурсивная сортировка слиянием работают нормально.   -  person user2968505    schedule 04.04.2014
comment
@Blastfurnace У меня была еще одна совершенно другая проблема в основном коде, но я полагаю, что этот конкретный вопрос можно считать ответом.   -  person user2968505    schedule 04.04.2014


Ответы (3)


int main()
{
    int data[SIZE];
    ...

объявляет массив в стеке. Есть ограничение на размер стека. Он зависит от ОС и конфигурации, но легко может быть меньше 12 МБ, суммы, которую вы запрашиваете (при условии, что 32-битные целые числа). Попробуйте выделить массив в куче вместо использования std::vector.

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

Если вам интересно узнать больше о том, как ОС обнаруживает переполнение стека, посмотрите виртуальную память, MMU и Guard Pages.

person japreiss    schedule 03.12.2014

Не уверен, что проблема именно в этом, но ваша сортировка слиянием кажется ошибочной.

Используйте целые числа без знака вместо знаковых.

person user541686    schedule 04.04.2014

person    schedule
comment
пожалуйста, всегда объясняйте, что вы делаете, добавляйте несколько строк описания перед вашим кодом - person Ahmed; 27.11.2014