2014 dxdy logo

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

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




На страницу 1, 2  След.
 
 Хто нагадил в память
Сообщение07.10.2009, 20:47 
Как обычно бывает в таких темах, я задам странный как на мой взгляд вопрос и получу "риторический ответ".
Но поскольку я озадачил этим вопросом друга уже полчаса как то я его выложу.
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 
Nerazumovskiy в сообщении #249908 писал(а):
Код:
Array::Array(const Array & a)
{
   if(m!=0x0000000)
   {
      printf("delete %d",m);
      delete[] m;
   }

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

 
 
 
 Re: Хто нагадил в память
Сообщение07.10.2009, 21:19 
Аватара пользователя
Еще в дополнение к сказанному хорошо бы в функциях присваивания проверять, что присваиваемый объект не нулевой. Возможно, системе не нравится попытка выделить память нулевого объема.

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

 
 
 
 Re: Хто нагадил в память
Сообщение07.10.2009, 21:31 
free я использовал от отчаянья :P

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

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

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

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

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

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

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

 
 
 
 Re: Хто нагадил в память
Сообщение07.10.2009, 21:50 
и в правду копирование я забыл профиксить.
Надо использовать исключения, мешает только то что я к ним непривык и код для меня усложняется, что мешает мне писать суть алгоритма.

 
 
 
 Re: Хто нагадил в память
Сообщение09.10.2009, 03:05 
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 
Насчет возвращения ссылки перегруженным оператором присваивания. Когда я говорил, что это позволит писать цепочки присваиваний вида a=b=c я всего-лишь имел ввиду, что при этом не будут создаваться лишние временные объекты (тоже своеобразная экономия памяти). Сами же многократные присваивания, понятное дело, можно будет писать в любом случае, даже если перегруженный оператор возвращает сам объект.

 
 
 
 Re: Хто нагадил в память
Сообщение11.10.2009, 16:03 
странную штуку заметил если писать
Код:
class BigInt
{...
inline BigInt operator-(const BigInt &b) const;
....
};
BigInt BigInt::operator-(const BigInt &b)const
{
.....
}

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

 
 
 
 Re: Хто нагадил в память
Сообщение11.10.2009, 18:26 
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 
2Nerazumovskiy
Попробуйте заменить class на struct, должно заработать. :) Проблема, кажется, в областях видимости.

 
 
 
 Re: Хто нагадил в память
Сообщение11.10.2009, 19:04 
venco в сообщении #250952 писал(а):
Уберите inline из объявления функции в хедере, может быть, поможет.

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

 
 
 
 Re: Хто нагадил в память
Сообщение11.10.2009, 19:17 
2Maslov
Но ведь у меня пример, приведенный Nerazumovskiy работает и с inline. Так в чем же, интересно, дело?

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

 
 
 
 Re: Хто нагадил в память
Сообщение11.10.2009, 21:52 
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  След.


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group