2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему На страницу 1, 2  След.
 
 Хто нагадил в память
Сообщение07.10.2009, 20:47 


23/12/08
245
Украина
Как обычно бывает в таких темах, я задам странный как на мой взгляд вопрос и получу "риторический ответ".
Но поскольку я озадачил этим вопросом друга уже полчаса как то я его выложу.
http :// rapidshare. com/files/289904468/main_array.rar.html.
тут лежит проект проект восьмой студии (с++) но его смотреть необязательно я выложу стоящие участки кода:

это конструктор
Код:
#include "limits.h"

#define Int unsigned int
#define Int_Max UINT_MAX
#define Iterator unsigned long
class Array
{
   Iterator s;//size
   Int *m;

public:
   Array(void);
.....
   Array(const Array&);
   virtual ~Array(void);
.....
......
   Array operator=(const Array&);
private:
};



Код:
Array::Array(void)
{
   m =0;
   s =0;
}
Array::Array(unsigned long a)
{
   m = new Int[a];
   if(m==NULL){ printf("FATAL ERROR MEMORY IS FULL");exit(1);}
   s = a;
   for(Iterator i=0;i<a;i++)
   {
      m[i] =0;
   }
}
Array::Array(const Array & a)
{
   if(m!=0x0000000)
   {
      printf("delete %d",m);
      delete[] m;
   }
   m = new Int[a.s];
   if(m==NULL){ printf("FATAL ERROR MEMORY IS FULL");exit(1);}

   s = a.s;
   for(Iterator i=0;i<s;i++)
   {
      this->m[i] = a.m[i];
   }
}

Array::~Array(void)
{
   //system("pause");
   if(m!=NULL)
   {
      printf("free  %d",m);
     free(m);
   }
}

[code]

[/code]
Array Array::operator =(const Array & a)
{
   if(m) delete[] m;

   m = new Int[a.s];
   if(m==NULL){ printf("FATAL ERROR MEMORY IS FULL");exit(1);}

   s = a.s;
   for(Iterator i=0;i<s;i++)
   {
      this->m[i] = a.m[i];
   }
   return *this;
}



ну тут всё просто, так вот когда я пишу
Код:
Array a(4),c;
c=a;

то всё идёт нормально, а потом когда чиститься память то вылетает :( я даже локализировал проблему до строчки
Код:
if(m!=0x0000000)
   {
      printf("delete %d",m);
      delete[] m;
   }

но всёравно ничего не могу придумать

 Профиль  
                  
 
 Re: Хто нагадил в память
Сообщение07.10.2009, 21:17 
Заслуженный участник


09/08/09
3438
С.Петербург
Nerazumovskiy в сообщении #249908 писал(а):
Код:
Array::Array(const Array & a)
{
   if(m!=0x0000000)
   {
      printf("delete %d",m);
      delete[] m;
   }

Тут у Вас, уж извините, ерунда какая-то :)
При создании объекта конструктором копирования m явно не инициализируется и содержит непонятно что. Вы же пытаетесь освободить память, на которую это "непонятно что" указывает. Зачем тут вообще что-то освобождать? Объект же только что создан, и буфер еще не выделен.

 Профиль  
                  
 
 Re: Хто нагадил в память
Сообщение07.10.2009, 21:19 
Супермодератор
Аватара пользователя


29/07/05
8248
Москва
Еще в дополнение к сказанному хорошо бы в функциях присваивания проверять, что присваиваемый объект не нулевой. Возможно, системе не нравится попытка выделить память нулевого объема.

Еще я заметил, что в одном месте Вы освобождаете память функцией free, хотя во всех остальных правильно используете delete[].

 Профиль  
                  
 
 Re: Хто нагадил в память
Сообщение07.10.2009, 21:31 


23/12/08
245
Украина
free я использовал от отчаянья :P

-- Ср окт 07, 2009 20:33:47 --

спссибо кстати/

 Профиль  
                  
 
 Re: Хто нагадил в память
Сообщение07.10.2009, 21:34 
Заслуженный участник


04/05/09
4587
PAV в сообщении #249925 писал(а):
Еще в дополнение к сказанному хорошо бы в функциях присваивания проверять, что присваиваемый объект не нулевой. Возможно, системе не нравится попытка выделить память нулевого объема.
Это как раз нормально и совершенно легальная операция. При этом стандарт говорит, что new Int[0] обязательно вернёт ненулевой указатель.

Цитата:
Еще я заметил, что в одном месте Вы освобождаете память функцией free, хотя во всех остальных правильно используете delete[].

Вот это действительно ошибка, естественно, в дополнение к настоящей проблеме, на которую указал Maslov.

А ещё всегда надо проверять в операторе присваивания, что объект не присваевается самому себе. В таком случае ничего делать не надо, иначе обычно просходит фигня типа копирования уже удалённой памяти и т.п.

А ещё нет смысла проверять на null после new и перед delete. Оператор new пошлёт исключение, a оператору delete (как и функции free()), можно давать null.

 Профиль  
                  
 
 Re: Хто нагадил в память
Сообщение07.10.2009, 21:50 


23/12/08
245
Украина
и в правду копирование я забыл профиксить.
Надо использовать исключения, мешает только то что я к ним непривык и код для меня усложняется, что мешает мне писать суть алгоритма.

 Профиль  
                  
 
 Re: Хто нагадил в память
Сообщение09.10.2009, 03:05 
Заслуженный участник


26/07/09
1559
Алматы
venco в сообщении #249932 писал(а):
А ещё всегда надо проверять в операторе присваивания, что объект не присваевается самому себе. В таком случае ничего делать не надо, иначе обычно просходит фигня типа копирования уже удалённой памяти и т.п.

Не соглашусь, что ничего не надо делать, надо вернуть себя. :) Что-то вроде if(this==&a) return *this.

И ещё по поводу оператора присваивания. Мне кажется, что нужно возвращать ссылку, т.е. прототип должен выглядеть как Array &Array::operator =(const Array &a). Вроде бы это позволит трактовать результат как lvalue и пользоваться вкусными присваиваниями типа a=b=c=d;

К тому же лучше в операторе присваивания и в копирующем конструкторе писать не m[i] = a.m[i], а m[i] = a[i] предварительно перегрузив оператор []. Кажется, желательно определить две его версии, одну как Int &Array::operator [](unsigned long){...}, а другую как const Int &Array::operator [](unsigned long) const {...}.

Кстати, при использовании класса Array можно будет писать такие вещи как Array array=5, и это скорее-всего будет корректным кодом (т.е. это эквивалентно Array array=Array(5)). Однако в силу чрезвычайной ненаглядности подобных неявных преобразований рекомендуется помечать конструкторы с одним обязательным параметром ключевым словом explicit.

 Профиль  
                  
 
 Re: Хто нагадил в память
Сообщение11.10.2009, 04:21 
Заслуженный участник


26/07/09
1559
Алматы
Насчет возвращения ссылки перегруженным оператором присваивания. Когда я говорил, что это позволит писать цепочки присваиваний вида a=b=c я всего-лишь имел ввиду, что при этом не будут создаваться лишние временные объекты (тоже своеобразная экономия памяти). Сами же многократные присваивания, понятное дело, можно будет писать в любом случае, даже если перегруженный оператор возвращает сам объект.

 Профиль  
                  
 
 Re: Хто нагадил в память
Сообщение11.10.2009, 16:03 


23/12/08
245
Украина
странную штуку заметил если писать
Код:
class BigInt
{...
inline BigInt operator-(const BigInt &b) const;
....
};
BigInt BigInt::operator-(const BigInt &b)const
{
.....
}

то не работает , а если влоб код функции в хедере написать то свё работает ?)
Странно както

 Профиль  
                  
 
 Re: Хто нагадил в память
Сообщение11.10.2009, 18:26 
Заслуженный участник


04/05/09
4587
Nerazumovskiy в сообщении #250924 писал(а):
странную штуку заметил если писать
Код:
class BigInt
{...
inline BigInt operator-(const BigInt &b) const;
....
};
BigInt BigInt::operator-(const BigInt &b)const
{
.....
}

то не работает , а если влоб код функции в хедере написать то свё работает ?)
Странно както

Уберите inline из объявления функции в хедере, может быть, поможет.

 Профиль  
                  
 
 Re: Хто нагадил в память
Сообщение11.10.2009, 18:58 
Заслуженный участник


26/07/09
1559
Алматы
2Nerazumovskiy
Попробуйте заменить class на struct, должно заработать. :) Проблема, кажется, в областях видимости.

 Профиль  
                  
 
 Re: Хто нагадил в память
Сообщение11.10.2009, 19:04 
Заслуженный участник


09/08/09
3438
С.Петербург
venco в сообщении #250952 писал(а):
Уберите inline из объявления функции в хедере, может быть, поможет.

+1.
inline - это подстановка тела функции в место вызова. Как компилятор может подставить тело, если он его не видит?

 Профиль  
                  
 
 Re: Хто нагадил в память
Сообщение11.10.2009, 19:17 
Заслуженный участник


26/07/09
1559
Алматы
2Maslov
Но ведь у меня пример, приведенный Nerazumovskiy работает и с inline. Так в чем же, интересно, дело?

 Профиль  
                  
 
 Re: Хто нагадил в память
Сообщение11.10.2009, 19:56 
Заслуженный участник


09/08/09
3438
С.Петербург
Circiter в сообщении #250973 писал(а):
2Maslov
Но ведь у меня пример, приведенный Nerazumovskiy работает и с inline. Так в чем же, интересно, дело?
А какой пример?
В том примере, который здесь приведен, inline не используется.
Так что, надо на Ваш код смотреть.

 Профиль  
                  
 
 Re: Хто нагадил в память
Сообщение11.10.2009, 21:52 
Заслуженный участник


26/07/09
1559
Алматы
2Maslov
Цитата:
А какой пример?

Я имел ввиду это:
Nerazumovskiy в сообщении #250924 писал(а):
Код:
class BigInt
{...
inline BigInt operator-(const BigInt &b) const;
....
};
BigInt BigInt::operator-(const BigInt &b)const
{
.....
}

Видите, проблема в том, что прототип оператора private. Если его перенести в public (да хоть, например, как я уже предлагал, сменив class на struct), то все зафурычит (т.е. можно будет вычитать объекты этого класса везде, где только этот класс виден).

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 18 ]  На страницу 1, 2  След.

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group