Очистка памяти
От: HunteX http://troyashka.ru/
Дата: 10.04.11 17:24
Оценка:
Всем привет! Есть следующий класс:

// cls.h
namespace nsp
{
 class cls
 {
  private:
   IplImage* image;
  public:
   void foo();
 };
}

// cls.cpp
namespace nsp
{
 void cls::foo()
 {
  // тут происходит инициализация cls::image и работа с cls::image
 }
}


Вопрос: как и где лучше удалить объект (очистить память, занимаемую объектом) cls::image ? Думаю, что и объект класса cls тоже надо будет удалить (очистить память, занимаемую объектом) ?

p.s. пытаюсь удалить cls::image в деструкторе cls, получаю ошибку ...
Re: Очистка памяти
От: c-smile Канада http://terrainformatica.com
Дата: 10.04.11 17:31
Оценка:
Здравствуйте, HunteX, Вы писали:

Надо так:

class cls
{
  private:
   IplImage* image;
  public:
   cls():image(0) {} // image <- 0, это необходимо 
   ~cls() { delete image; }
   void foo();
};
Re[2]: Очистка памяти
От: HunteX http://troyashka.ru/
Дата: 10.04.11 17:37
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Надо так:


CS>
CS>class cls
CS>{
CS>  private:
CS>   IplImage* image;
CS>  public:
CS>   cls():image(0) {} // image <- 0, это необходимо 
CS>   ~cls() { delete image; }
CS>   void foo();
CS>};
CS>


Хм ... непонятен этот момент:

cls():image(0) {} // image <- 0, это необходимо


Даже не знаю, что и сказать ... Можно чуть поподробнее ?
Re[3]: Очистка памяти
От: Cyberax Марс  
Дата: 10.04.11 17:41
Оценка:
Здравствуйте, HunteX, Вы писали:

HX>
HX>cls():image(0) {} // image <- 0, это необходимо 
HX>

HX>Даже не знаю, что и сказать ... Можно чуть поподробнее ?
Если не инициализировать указатель image явно, то в нём будет мусор (неопределённое поведение). Соответственно, "delete image" тоже вызовет неопределённое поведение (на практике, скорее всего SIGSEGV).
Sapienti sat!
Re[3]: Очистка памяти
От: enji  
Дата: 10.04.11 17:46
Оценка:
HX>Хм ... непонятен этот момент:

HX>
HX>cls():image(0) {} // image <- 0, это необходимо 
HX>


HX>Даже не знаю, что и сказать ... Можно чуть поподробнее ?


Если не инициализировать указатель, в нем будет мусор. В деструкторе вы не сможете определить, был ли создан объект и надо ли его удалять. Применение delete к мусорному указателю приведет к расстрелу памяти.

А вообще, юзайте boost::scoped_ptr или std::auto_ptr — они автоматом инициализируются и уничтожают объект
Re[4]: Очистка памяти
От: HunteX http://troyashka.ru/
Дата: 10.04.11 17:47
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Здравствуйте, HunteX, Вы писали:


HX>>
HX>>cls():image(0) {} // image <- 0, это необходимо 
HX>>

HX>>Даже не знаю, что и сказать ... Можно чуть поподробнее ?
C>Если не инициализировать указатель image явно, то в нём будет мусор (неопределённое поведение). Соответственно, "delete image" тоже вызовет неопределённое поведение (на практике, скорее всего SIGSEGV).

Да, вроде такая была ошибка, но вот что странно — ведь я инициализирую cls::image в функции foo()! То есть я работаю с этим объектом и указатель ссылается на память, которая была выделена ... Или обязательно инициализировать указатель image ИМЕННО таким образом:

cls():image(0) {} // image <- 0, это необходимо


p.s. немного не по теме: Пишу на Qt ... пересел на него с Visual Studio ... что-то отладчик совсем плохой или я просто не настроил его ... в VS при отладке наведя на переменную можно узнать её значение и полазить по свойствам ... может и в Qt это можно сделать поудобнее?
Re[4]: Очистка памяти
От: HunteX http://troyashka.ru/
Дата: 10.04.11 17:49
Оценка:
Здравствуйте, enji, Вы писали:

HX>>Хм ... непонятен этот момент:


HX>>
HX>>cls():image(0) {} // image <- 0, это необходимо 
HX>>


HX>>Даже не знаю, что и сказать ... Можно чуть поподробнее ?


E>Если не инициализировать указатель, в нем будет мусор. В деструкторе вы не сможете определить, был ли создан объект и надо ли его удалять. Применение delete к мусорному указателю приведет к расстрелу памяти.


E>А вообще, юзайте boost::scoped_ptr или std::auto_ptr — они автоматом инициализируются и уничтожают объект


Видимо это то, что мне необходимо (перешел с C# на C++ ну очень тяжело, но терпимо )
Re[3]: Очистка памяти
От: c-smile Канада http://terrainformatica.com
Дата: 10.04.11 17:52
Оценка:
Здравствуйте, HunteX, Вы писали:

HX>Даже не знаю, что и сказать ... Можно чуть поподробнее ?


Это начальная инициализация полей в конструктор-функции.
Если есть несколько полей в классе которые должны иметь начальное состояние то конструктор пишут так:

cls()
  :field1(0), field2(12) // инициализация полей
  {
    // тело конструктора
  }


В принципе это эквивалентно вот этому:

cls()
  {
    field1 = 0; 
    field2 = 12; // инициализация полей

    // тело конструктора
  }
Re[4]: Очистка памяти
От: HunteX http://troyashka.ru/
Дата: 10.04.11 18:01
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Это начальная инициализация полей в конструктор-функции.

CS>Если есть несколько полей в классе которые должны иметь начальное состояние то конструктор пишут так:

CS>
CS>cls()
CS>  :field1(0), field2(12) // инициализация полей
CS>  {
CS>    // тело конструктора
CS>  }

CS>


CS>В принципе это эквивалентно вот этому:


CS>
CS>cls()
CS>  {
CS>    field1 = 0; 
CS>    field2 = 12; // инициализация полей

CS>    // тело конструктора
CS>  }
CS>


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

// cls.h
namespace nsp
{
 class cls
 {
  private:
   IplImage* image;
  public:
   void foo();
   cls();
 };
}

// cls.cpp
namespace nsp
{
 cls::cls()
 {
  image = 0;
 }
 // либо так cls::cls():image(0) {}

 void cls::foo()
 {
  // работа с cls::image
 }
}


А то я увидев cls::cls():image(0) уже подумал про наследование и решил что схожу с ума
Re[5]: Очистка памяти
От: о_О
Дата: 10.04.11 18:03
Оценка:
Здравствуйте, HunteX, Вы писали:

HX>Даже не знаю, что и сказать ... Можно чуть поподробнее ?

...
HX>Видимо это то, что мне необходимо (перешел с C# на C++ ну очень тяжело, но терпимо :) )

прочти уже учебник, лодырь. тут ситуация такая:

Гинеколог — стоматологу: "Это тебе не в зубах ковыряться!"

Re[6]: Очистка памяти
От: HunteX http://troyashka.ru/
Дата: 10.04.11 18:13
Оценка:
Здравствуйте, о_О, Вы писали:

о_О>Здравствуйте, HunteX, Вы писали:


HX>>Даже не знаю, что и сказать ... Можно чуть поподробнее ?

о_О>...
HX>>Видимо это то, что мне необходимо (перешел с C# на C++ ну очень тяжело, но терпимо )

о_О>прочти уже учебник, лодырь. тут ситуация такая:

о_О>

о_О>Гинеколог — стоматологу: "Это тебе не в зубах ковыряться!"


Я стараюсь, просто столько всего изучаю, что просто нет времени ПРОчитать полностью приличный учебник по C++, приходится на лету учить и мучать людей глупыми вопросами
p.s. сейчас учу С++, Qt, OpenCV, GDI+, немного комп. графику и цифровую обработку изображений ... как появляется время почитываю Шилдта "C++. Руководство для начинающих"
Re[7]: Очистка памяти
От: о_О
Дата: 10.04.11 18:25
Оценка:
Здравствуйте, HunteX, Вы писали:

HX>p.s. сейчас учу Qt, OpenCV, GDI+, немного комп. графику и цифровую обработку изображений

это всё бесполезно, пока возникают такие вопросы. но в ногу ты себе уже выстрелил (простые типы в с++ не инициализируются по умолчанию)
Re[2]: Очистка памяти
От: wvoquine  
Дата: 10.04.11 18:31
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Здравствуйте, HunteX, Вы писали:


CS>Надо так:


CS>
CS>class cls
CS>{
CS>  private:
CS>   IplImage* image;
CS>  public:
CS>   cls():image(0) {} // image <- 0, это необходимо 
CS>   ~cls() { delete image; }
CS>   void foo();
CS>};
CS>


А почему не сказать человеку, что это далеко не единственная проблема в его коде, которая может стать причиной такого поведения?

Может cls копируется во временный объект, который в своём деструкторе всё и чистит. А потом постоянный объект падает в деструкторе. Нужно конструктор копирования запретить, и тогда можно и auto_ptr заюзать
To be is to be the value of a variable
Re[3]: Очистка памяти
От: HunteX http://troyashka.ru/
Дата: 10.04.11 19:11
Оценка:
Здравствуйте, wvoquine, Вы писали:

W>А почему не сказать человеку, что это далеко не единственная проблема в его коде, которая может стать причиной такого поведения?


W>Может cls копируется во временный объект, который в своём деструкторе всё и чистит. А потом постоянный объект падает в деструкторе. Нужно конструктор копирования запретить, и тогда можно и auto_ptr заюзать


Хм, я специально почитаю учебник, чтобы понять то, что Вы написали про запрет конструктора копирования, остальное вроде бы понятно ... csl не копируется во временный объект, а используется как (все конечно же упрощено)

cls *c = new cls();
// работа с c->
Re[4]: Очистка памяти
От: Ops Россия  
Дата: 10.04.11 19:28
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Здравствуйте, HunteX, Вы писали:


HX>>Даже не знаю, что и сказать ... Можно чуть поподробнее ?


CS>Это начальная инициализация полей в конструктор-функции.

CS>Если есть несколько полей в классе которые должны иметь начальное состояние то конструктор пишут так:

CS>
CS>cls()
CS>  :field1(0), field2(12) // инициализация полей
CS>  {
CS>    // тело конструктора
CS>  }

CS>


CS>В принципе это эквивалентно вот этому:


CS>
CS>cls()
CS>  {
CS>    field1 = 0; 
CS>    field2 = 12; // инициализация полей

CS>    // тело конструктора
CS>  }
CS>


Это не эквивалентно. Хотя в первом приближении для начинающего и похоже.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Re[5]: Очистка памяти
От: Ytz https://github.com/mtrempoltsev
Дата: 10.04.11 19:37
Оценка:
Здравствуйте, HunteX, Вы писали:

HX>p.s. немного не по теме: Пишу на Qt ... пересел на него с Visual Studio ... что-то отладчик совсем плохой или я просто не настроил его ... в VS при отладке наведя на переменную можно узнать её значение и полазить по свойствам ... может и в Qt это можно сделать поудобнее?


Qt — фреймворк, а не IDE, работать с Qt можно и в Visual Studio, как впрочем и с любыми другими библиотеками. Или ты имеешь в виду Qt Creator? Если так, то убедись, что код который отлаживаешь собран отладочной информацией (debug).

Кстати, в VS очень удобный отладчик, но когда привыкнешь к отладочной печати, то отладчики будут редко нужны.
Re[7]: Очистка памяти
От: Ytz https://github.com/mtrempoltsev
Дата: 10.04.11 19:42
Оценка:
Здравствуйте, HunteX, Вы писали:

HX> Я стараюсь, просто столько всего изучаю, что просто нет времени ПРОчитать полностью приличный учебник по C++, приходится на лету учить и мучать людей глупыми вопросами

HX>p.s. сейчас учу С++, Qt, OpenCV, GDI+, немного комп. графику и цифровую обработку изображений ... как появляется время почитываю Шилдта "C++. Руководство для начинающих"

Результат этого — каша в голове и отвратительный код. Заставь себя месяц ничего не писать, пока не прочтешь толковый учебник по С++ (Шилдт вроде как макулатура, рекомендую Эккеля "Философия С++").
Re: Очистка памяти
От: Ytz https://github.com/mtrempoltsev
Дата: 10.04.11 19:47
Оценка:
// cls.h
namespace nsp
{
 class cls
   : private boost::noncopyable 
 {
 private:
   std::auto_ptr<IplImage> image;
 public:
   void foo();
 };
}

// cls.cpp
namespace nsp
{
  void cls::foo()
  {
     image.reset(new IplImage());
  }
}
Re: Очистка памяти
От: HunteX http://troyashka.ru/
Дата: 10.04.11 20:12
Оценка:
Спасибо ВСЕМ за помощь, обязательно учту ваши советы! Тема закрыта!
Re[5]: Очистка памяти
От: c-smile Канада http://terrainformatica.com
Дата: 10.04.11 20:37
Оценка:
Здравствуйте, Ops, Вы писали:

Ops>Это не эквивалентно. Хотя в первом приближении для начинающего и похоже.


Вопрошающему: эквивалентно но не тождественно. Так пойдет?

Хунтексу: в первом случае срабатывают инициализирующие конструкторы [полей].
Во втором случае может работатает operator=() который присваивает нечто в поле которое уже должно быть инициализировано к этому моменту.
Т.е. возможно разное поведение.

Хунтексу #2: В С# область памяти внутри new инициализируется нулями. В C++ начальные значения нужно писать явно. Это надо помнить.
Т.е. у тебя в image лежит мусорный указатель. Попытка его удаления — как правило заканчивается с треском.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.