Динамически выделенные массивы и HEAP повреждены

Я пытаюсь написать программу, которая принимает входные данные в виде динамического массива и сортирует их от самого низкого до самого высокого, а затем отображает от самого высокого до самого низкого. Однако я получаю сообщение об ошибке отладки: «ОБНАРУЖЕНО ПОВРЕЖДЕНИЕ КУЧИ: после нормального блока (№ 182) по адресу 0x010CE3E8. CRT обнаружил, что приложение записывает в память после окончания буфера кучи».

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

void insert_Array(int Array1[], int array_size)
{
    for (int counter = 0; counter < array_size; ++counter)
    {
         cout << " Please enter the " << counter << " number : ";
         cin >> Array1[counter];
    }
    return;
}

void swap(int* a, int* b)
{
    int holder = *a;
    *a = *b;
    *b = holder;
}

void sort_Array(int Array1[], int array_size)
{
    int lowestNum_index;
    for (int counter1 = 0; counter1 < array_size; ++counter1)
    {
        for (int counter2 = counter1; counter2 < array_size; ++counter2)
        {
            if (Array1[counter2] < Array1[counter2 + 1])
                lowestNum_index = counter2;
            else
                lowestNum_index = counter2 + 1;
        }
        swap(Array1[counter1], Array1[lowestNum_index]);
    }
    return;
}

Основная функция

int* npointer = new int[nNumbers];
insert_Array(npointer, nNumbers);
sort_Array(npointer, nNumbers);
cout << " The number you desired is " << nNumbers << endl;

cout << " The numbers in the array from  high to low are ";
for (int i = 0; i < nNumbers; ++i)
{
    cout << *(npointer + nNumbers - i) << " ";
}

cout << endl;
delete [] npointer;

Когда я запускаю программу, она успешно сортирует числа, которые я даю, от большего к меньшему.

ОБНАРУЖЕНО ПОВРЕЖДЕНИЕ КУЧИ: после нормального блока (#182) по адресу 0x010CE3E8. CRT обнаружил, что приложение записывает в память после окончания буфера кучи.


person Rufat Imanov    schedule 31.05.2019    source источник
comment
хорошо, я должен спросить - почему вы делаете все это, когда std::vector существует, и он существует более 21 года в стандартной библиотеке C++? Во-вторых, вся работа находится внутри insert_Array и sort_Array — вы должны были опубликовать этот код.   -  person PaulMcKenzie    schedule 31.05.2019
comment
К сожалению, это домашнее задание   -  person Rufat Imanov    schedule 31.05.2019
comment
Что ж, программа успешно строится и запускается -- она ​​не запускается успешно. Опубликуйте минимально воспроизводимый пример.   -  person PaulMcKenzie    schedule 31.05.2019
comment
При печати: *(npointer + nNumbers - i) это кажется ошибкой на единицу, должно быть *(npointer + nNumbers - i - 1). Кроме этого, вы не показываете, что делают insert_Array и sort_Array, так что если там есть проблема, мы не сможем сказать.   -  person Qubit    schedule 31.05.2019
comment
Ошибка, скорее всего, вызвана записью за пределы массива, так как вы не пишете в массив в опубликованном коде, мы не можем вам помочь, ошибка, скорее всего, в insert_Array или sort_Array. Опубликуйте минимально воспроизводимый пример   -  person Alan Birtles    schedule 31.05.2019
comment
if (Array1[counter2] < Array1[counter2 + 1]) -- Что произойдет, если counter2 равно array_size - 1? Видите там проблему?   -  person PaulMcKenzie    schedule 31.05.2019
comment
Метод сортировки кажется мне довольно неправильным.   -  person Avin Kavish    schedule 31.05.2019
comment
Вы используете Visual Studio? Если да, то просто для удовольствия измените свою функцию sort_array на эту: void sort_Array(int Array_test[], int array_size) {std::vector<int> Array1(Array_test, Array_test + array_size); и больше ничего не меняйте. Запустите программу, используя отладочную сборку. Теперь следите за ошибками, которые среда выполнения отметит для вас. Как только вы исправите эти ошибки, вернитесь к массиву.   -  person PaulMcKenzie    schedule 31.05.2019
comment
@PaulMcKenzie, в его логике инициализации массива нет ничего плохого, просто сортировка.   -  person Avin Kavish    schedule 31.05.2019
comment
Есть куча коррупции, то есть он что-то портит. Сделав то, что я предложил, ОП сам увидит, в чем ошибка. Иногда неиспользование std::vector просто усложняет поиск этих ошибок.   -  person PaulMcKenzie    schedule 31.05.2019
comment
У меня нет ошибок @PaulMcKenzie   -  person Rufat Imanov    schedule 31.05.2019
comment
@RufatImanov -- Вы используете Visual Studio? Определенно появится всплывающее диалоговое окно assert, если вы запустили программу и использовали простой тестовый массив, такой как {3,2,1}. Этот пример программы выдает ошибку в Visual Studio, сборка отладки   -  person PaulMcKenzie    schedule 31.05.2019


Ответы (1)


Обычно при выполнении вложенного цикла такого типа внутренний цикл задается так, чтобы он начинался с внешнего цикла + 1. Чтобы вы не получили такие значения, как это Array1[counter2 + 1], что приводит к нелегальному доступу к памяти за пределами границ массива на последняя итерация цикла.

Даже с этим исправлением логика сортировки неверна. То, что вы пытаетесь сделать, известно как сортировка выбора, при которой вы сравниваете каждый элемент массива с остальными элементами с временной сложностью n ^ 2. Вы должны получить lowestNum_index для каждой итерации внешнего цикла, а не весь массив. Вот как я бы сделал сортировку выбором.

void sort_Array(int Array[], int array_size)
{
  for (int i = 0; i < array_size; ++i)
  {
    int lowestIdx = i; // <-- always starts at i
    for (int j = i + 1; j < array_size; ++j)
      if (Array[j] < Array[i])
        lowestIdx = j;

    swap(&Array[lowestIdx], &Array[i]); // <--- note the & symbol to pass by reference
  }
}

Поскольку ваша функция подкачки принимает два указателя, использование Array[i] приведет к нелегальному доступу к памяти, поскольку оператор [] разыменовывает массив до значения в i, вы должны использовать оператор &, чтобы получить адрес для этого местоположения. то есть

Array[i] = *(Array + i)
&Array[i] = Array + i // <--- essentially cancels the dereference operator

Изменить: инициализировать lowestIdx = i в каждом внешнем цикле.

person Avin Kavish    schedule 31.05.2019
comment
Допустил небольшую ошибку, исправил. - person Avin Kavish; 31.05.2019