Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Массив перезаписывает глобальную переменную.

12K
08 июня 2006 года
andrystepa
24 / / 08.06.2006
Простая программка - из упражнений к Самоучителю C++ Шилдта. Задача: создать класс "очередь", и затем присвоить одной очереди другую.
[COLOR="Red"]Заголовочный файл q-type.h:[/COLOR]
#pragma once
#include <iostream>
using namespace std;


class q_type
{
int tail, head,SIZE;
//int* p_queue;
int queue[];
public:

q_type(int s);
void q(int num); //Запоминание
int deq(); //Удаление из начала очереди

//public:
// ~q_type(void);
};

[COLOR="Red"]Файл q_type.cpp:[/COLOR]

#include "q_type.h"


q_type::q_type(int s)
{
head=tail=0;
SIZE=s;
//int queue[];
//p_queue= new queue[SIZE];
}
void q_type::q(int num)
{
if(tail+1==head || (tail+1==SIZE && !head))
{
cout<<"Очередь полна*!\n";
return;
}
tail++;
if (tail==SIZE) tail=0;
queue[tail]=num;
cout<<"Адрес элемента: "<<tail<<" равен "<<&queue[tail]<<"\n";
}
int q_type::deq()
{
if (head==tail) {
cout<<"Очередь пуста*\n";
return 0;
}
head++;
if(head==SIZE) head=0;
return queue[head];
}

[COLOR="Red"]Файл queue.cpp:[/COLOR]

#include <iostream>
#include "q_type.h"
using namespace std;

int main()
{
int s;
cout<<"Введите размер очереди > ";
cin>>s;
cout<<"\n";
q_type q1(s);
q_type q2(s);
cout<<"Addres Адрес S:"<<&s<<"\n";
int l;
for(l=0; l<s; l++)
{
q1.q(l);
q2.q(l*l);
}
cout<<"Текущие очереди:\n";
for (l=0; l<s; l++)
{
cout<<"Элемент очереди 1: "<<q1.deq()<<" очереди 2: "<<q2.deq()<<"\n";
}
cout<<"Присваивание. Нажмите любую клавишу, затем Enter.\n";
char c;
cin>>c;
q1=q2;
for (l=0; l<s; l++)
{
cout<<"Элемент очереди 1: "<<q1.deq()<<" Очереди 2: "<<q2.deq()<<"\n";
}
cout<<"Для выхода нажмите любую клавишу, затем Enter.*";
cin>>c;
return 0;
}
При запуске видно (пришлось добавить строчки с выводом адресов переменных), что при втором присваивании элементу очереди q1, он записывается на место глобальной переменной s. Как этого можно избежать?
Второй вопрос. При выходе из программы выдается ошибка:
Run-Time Check Failure #2 - Stack around the variable 'q1' was corrupted.
Почему она появляется, и как этого избежать? (похоже дело с неверной работой деструктора, но в чем конкретно?)
Архив с exe-шником приложен.
350
09 июня 2006 года
cheburator
589 / / 01.06.2006
Не совсем понятно, почему ты закомментировал объявление p_queue как указателя на int и сделал его "безразмерным" массивом. Но главное не это, а то что ты закомментировал почему-то выделение необходимого количества памяти под него в конструкторе (и соответственно освобождение памяти в деструкторе). Система ведь на этапе компиляции не знает, какого размера будет очередь, и не может сама выделить ей нужное место, так что это твоя забота.
А так получается, что ты при попытке поставить очередное число в очередь (т. е. в методе q()) будешь производить запись в область памяти, не принадлежащую массиву queue, а (возможно, и скорее всего) принадлежащую кому-то другому. Может даже машинному коду программы. В данном случае ты видимо попадаешь на то место, где хранится твоя переменная s (кстати, она вовсе не глобальная), а также нарушаешь стек, чем и вызваны оба твоих вопроса.
К тому же, для правильного копирования очереди в очередь нужно сначала в той очереди, куда происходит копирование, освободить память, затем снова выделить уже того размера, который в копируемой очереди. Т. к. в очереди-приемнике queue может оказаться меньше, и при копировании ты выйдешь за пределы "своей" памяти и что-то опять нарушишь. В общем, напиши оператор копирования:

 
Код:
q_type& q_type::operator = (q_type &op)
{
  delete queue;
  queue = new int [op.SIZE];
  memcpy (queue, op.queue, sizeof(int)*op.SIZE);
  SIZE = op.SIZE;
  head = op.head;
  tail = op.tail;
  return *this;
};

или аналогичный по содержимому копи-конструктор q_type::q_type (q_type &op)
12K
14 июня 2006 года
andrystepa
24 / / 08.06.2006
[QUOTE=cheburator]Не совсем понятно, почему ты закомментировал объявление p_queue как указателя на int и сделал его "безразмерным" массивом./QUOTE]
Спасибо. Правда я сам понял в чем дело - компилятор не программист, и понять, чего хочет программист по общему виду программы он, к сожалению, не в состоянии (иначе бы и программист был бы не нужен:) ). Закомментировал я эту строку, потому что сразу не сообразил, как этот массив выделить динамически, и попробовал прорваться на халяву - за счет компилятора. Не вышло, пришлось переписывать с new и delet'ами.
А вот насчет копирования, в данном случае обе очереди абсолютно одинаковы по размеру и типу. Так что освобождать - выделять по новому память не надо. Хотя, конечно, по правильному надо писать конструктор копий.
Еще раз спасибо!
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог