Невозможно удалить весь массив в C … если я попытаюсь снова отобразить массив, первые два значения будут мусорными, остальные те же

#c #arrays #stack

#c #массивы #стек

Вопрос:

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

 #include<iostream.h>
#include<conio.h>
template<class T>
class stack
{
    int capacity;
public:
    T *array;
    int top;
    stack(int);
    void push(T);
    T pop();  
    int stackempty();
    int stackfull();
    void display();
    void deletestack();
};

template<class T>
stack<T>::stack(int max)
{
   top=-1;
   capacity=max;
   array=new T[capacity]; 
}

template<class T>
void stack<T>::push(T data)
{  
   if(stackfull())
      cout<<"stack overflow";
   else
      array[  top]=data;
}

template<class T>
T stack<T>::pop() 
{ 
    if(stackempty())
    {
       cout<<"stack underflow"; 
       return -1;
    }
    else 
       return array[top--];
}



template<class T>
int stack<T>::stackempty()
{ 
   if(top==-1) 
      return 1;
   else 
      return 0;
}

template<class T>
int stack<T>::stackfull()
{ 
   if(top==capacity-1)
      return 1;
   else 
      return 0;
}

template<class T>
void stack<T>::display()
{
   int i;
   if(top==-1)
      cout<<"empty stack";
   else
      for(i=0;i<=top;i  )
        cout<<"n"<<array[i];
}

template<class T>
void stack<T>::deletestack()
{
    delete []array; 
}

int main()
{
   stack<int>* S=new stack<int>(20);
   clrscr();
   S->push(5);
   S->push(10);
   S->push(15);
   S->display();
   S->deletestack();
   S->display();
   S->push(5);
   S->display();
   getch();
   return 0;
}
  

Комментарии:

1. Если вы хотите очистить свой стек, тогда сделайте top = -1; вместо delete[] array; . То, как вы спроектировали свой стек, заключается в том, что предполагается, что в нем всегда должны capacity быть выделены элементы, и top указывается, сколько из этих элементов «используется».

Ответ №1:

Это намного больше кода, чем необходимо для иллюстрации этой проблемы, но в любом случае… Если вы delete[] используете массив, повторный доступ к нему является неопределенным поведением. При повторном доступе к нему ваша программа может вообще что-либо делать.

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

Комментарии:

1. @nightshade Нет! Это определенно не разрешено c (или эквивалентно c с malloc помощью / free ). Компилятор превратит его во что-то, что будет выполняться, и код будет выглядеть c , но он больше не является (действительным) c .

2. это не то, что означает запретить… его программа не зависала, когда он пытался получить доступ… предоставление неопределенного поведения — это не то же самое, что «не разрешить»… Я думаю, что это неопределенное поведение должно быть вместо сбоев (очень помогло бы в отладке)

3. Почему это должно произойти сбой? Вы нарушили контракт. Вы проиграли. И на техническом уровне, почему это должно произойти сбой? Вы обращаетесь к памяти в адресном пространстве вашей программы. Если это произошло с ошибкой, это потому, что вы сделали что-то, запрещенное операционной системой , а не языком .

Ответ №2:

Представьте, что у вас есть несколько домов в колонии. Теперь они вам не принадлежат. Это не означает, что эти дома разрушены. Может случиться так, что дома есть как есть. Может случиться, что там нет дома.

Аналогично, память, выделенная для вашего массива, все еще существует, и у вас есть его адрес. Может случиться так, что местоположение имеет те же данные или нет.

Ответ №3:

Строка delete []array; в вашем методе deletestack() освободит массив памяти, на который указывает вызываемый указатель array . (однако free — это не то же самое, что записать поверх него что-то другое)

После вызова delete вы возвращаете память операционной системе, доступ к ней после ее возврата в операционную систему является неопределенным поведением. Иногда это приведет к ошибке сегментации и сбою, а иногда ничего плохого не произойдет. C в этом отношении сильно отличается от таких языков, как Java, которые активно ищут незаконный доступ к памяти и немедленно выдают исключение. В C ожидается, что программист будет следовать правилам, и никто не проверяет его.

В любом случае освобождение памяти не означает, что она очищена. Старые значения, которые вы туда поместили, все еще существуют до тех пор, пока что-то другое не выделит эту память и не начнет записывать в нее.

В опубликованном вами коде есть много других проблем, которые могут вызвать странное поведение, если он используется:

  • stack<int>* S=new stack<int>(20); выделил объект в куче, который никогда не удаляется.
  • класс stack выделяет массив во время построения, однако dtor не освобождает массив. Пользователь, который забывает позвонить deletestack , приведет к утечке памяти
  • класс stack содержит ссылку на выделенный массив, однако у него нет copy-ctor или operator=, и он их не удаляет.