Re[3]: tring to joke
От: Кодт Россия  
Дата: 24.06.08 08:35
Оценка: :))
Здравствуйте, Vamp, Вы писали:

V>Интересно, что голый противопоставлен умному. Вот я, например, бываю голым, но от этого не становлюсь менее умным...


Зато выглядишь глупо
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re: std:stack вызов деструктора
От: Кодт Россия  
Дата: 23.06.08 13:21
Оценка: +1
Здравствуйте, <Аноним>, Вы писали:

А>Вопрос, как вызвать деструкторы объектов размещенных

А>в std:stack чтобы не было утечки памяти. Спасибо.

Храни в стеке не голые указатели, а умные. А именно, boost::shared_ptr (std::auto_ptr здесь не годится).
typedef boost::shared_ptr<A> A_ptr;
{
std::stack<A_ptr> s2;
s2.push(A_ptr(new A));
s2.push(A_ptr(new A(88));
s2.push(A_ptr(new A(99));
s2.pop(); // нет утечки
}// деструкция стека - снова нет утечки
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
std:stack вызов деструктора
От: Аноним  
Дата: 23.06.08 12:49
Оценка:
Вопрос, как вызвать деструкторы объектов размещенных
в std:stack чтобы не было утечки памяти. Спасибо.

class A{
    int a;
public:
    A(int i=77 ): a(i) {}
    ~A(){ cout<<"~A"<<a<<endl; }
};

int main(){
    int d[]={45,34,56,27,71,50,62};
      {
     stack <A> s1;
     A a1, a2(88), a3(99);
     s1.push(a1); s1.push(a2); s1.push(a3);
     s1.pop();//вызвался деструктор 
    }//вызвались встальные деструкторы
      {
    stack <A*> s2;
    s2.push(new A);
      s2.push(new A(88));
    s2.push(new A(99));
    s2.pop();//утечка 1 ????
    }//утечка остальных ????
Re: std:stack вызов деструктора
От: Pasternak  
Дата: 23.06.08 13:08
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Вопрос, как вызвать деструкторы объектов размещенных

А>в std:stack чтобы не было утечки памяти. Спасибо.

А>
А>class A{
А>    int a;
А>public:
А>    A(int i=77 ): a(i) {}
А>    ~A(){ cout<<"~A"<<a<<endl; }
А>};

А>int main(){
А>    int d[]={45,34,56,27,71,50,62};
А>      {
А>     stack <A> s1;
А>     A a1, a2(88), a3(99);
А>     s1.push(a1); s1.push(a2); s1.push(a3);
А>     s1.pop();//вызвался деструктор 
А>    }//вызвались встальные деструкторы
А>      {
А>    stack <A*> s2;
А>    s2.push(new A);
А>      s2.push(new A(88));
А>    s2.push(new A(99));
А>    s2.pop();//утечка 1 ????
А>    }//утечка остальных ????

А>


Использовать boost::shared_ptr

    stack <boost::shared_ptr<A> > s2; 
    ...
    s2.pop(); 
    //утечек больше не будет
Re: std:stack вызов деструктора
От: Were  
Дата: 23.06.08 13:10
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Вопрос, как вызвать деструкторы объектов размещенных

А>в std:stack чтобы не было утечки памяти. Спасибо.

Умные указатели, либо руками:
    delete s2.top();
    s2.pop();

    while( !s2.empty())
    {
        delete s2.top();
        s2.pop();
    }
Re[2]: std:stack вызов деструктора
От: Аноним  
Дата: 23.06.08 13:31
Оценка:
Здравствуйте, Кодт, Вы писали:


К>Храни в стеке не голые указатели, а умные. А именно, boost::shared_ptr (std::auto_ptr здесь не годится).


Спасибо за ответы, но посмотрел внимательнее
и увидил несоответствие вызовов деструкторов
  stack <A> s100;
  A a1,a2(88),a3(99);
  s1.push(a1);s1.push(a2);s1.push(a3);
  s1.pop();//вызвался деструктор ~A99
    }// ~A99 ~A88 ~A77 ~A88 ~A77

Зачем по два раза убивть.
Re[3]: std:stack вызов деструктора
От: Анатолий Широков СССР  
Дата: 23.06.08 13:41
Оценка:
А>Зачем по два раза убивть.

А вы расширьте интерфейс вашего класса и ответ станет очевиден:

class A{
    int a;
public:
    A(int i=77 ): a(i) {cout<<"ctor"<<a<<endl;}
    A(const A &o): a(o.i) {cout<<"cctor"<<a<<endl;}
    ~A(){ cout<<"~A"<<a<<endl; }
};
Re[3]: std:stack вызов деструктора
От: AlexCrush Россия  
Дата: 23.06.08 13:44
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Кодт, Вы писали:


А>Спасибо за ответы, но посмотрел внимательнее

А>и увидил несоответствие вызовов деструкторов
А>
А>  stack <A> s100;
А>  A a1,a2(88),a3(99);
А>  s1.push(a1);s1.push(a2);s1.push(a3);
А>  s1.pop();//вызвался деструктор ~A99
А>    }// ~A99 ~A88 ~A77 ~A88 ~A77
А>

А>Зачем по два раза убивть.

Вы вставьте еще печать в конструкторе и копи-конструкторе A, и увидите что к чему.
Запись A a(99) приводит к созданию 1-го локального объекта, а s1.push(a) — к созданию его копии в контейнере. Объект a убивается при его выходе из области видимости, а его копия в контейнере — в момент s1.pop() или смерти контейнера s1
Re[4]: std:stack вызов деструктора
От: Аноним  
Дата: 23.06.08 13:52
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:


АШ>А вы расширьте интерфейс вашего класса и ответ станет очевиден:


Спасибо что помогли расширить мозг — понял.
Re: std:stack вызов деструктора
От: Юрий Жмеренецкий ICQ 380412032
Дата: 23.06.08 14:11
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Вопрос, как вызвать деструкторы объектов размещенных

А>в std:stack чтобы не было утечки памяти. Спасибо.

А>
А>class A{
А>    int a;
А>public:
А>    A(int i=77 ): a(i) {}
А>    ~A(){ cout<<"~A"<<a<<endl; }
А>};

А>int main(){
А>    int d[]={45,34,56,27,71,50,62};
А>      {
А>     stack <A> s1;
А>     A a1, a2(88), a3(99);
А>     s1.push(a1); s1.push(a2); s1.push(a3);
А>     s1.pop();//вызвался деструктор 
А>    }//вызвались встальные деструкторы
А>      {
А>    stack <A*> s2;
А>    s2.push(new A);
А>      s2.push(new A(88));
А>    s2.push(new A(99));
А>    s2.pop();//утечка 1 ????
А>    }//утечка остальных ????

А>


Помимо того, что уже сказали, добавлю что в каждой из выделенных строк возможна утечка. Если при переаллокации памяти в push вылетит исключение, то утекет добавляемый объект. Как вариант, лечится так:
std::auto_ptr<A> a(new A(1));
s2.push_back(a.get());
a.release();
Re[2]: std:stack вызов деструктора
От: Аноним  
Дата: 23.06.08 19:29
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:
Если при переаллокации памяти в push вылетит исключение, то утечет добавляемый объект. Как вариант, лечится так:
ЮЖ>
ЮЖ>std::auto_ptr<A> a(new A(1));
ЮЖ>s2.push_back(a.get());
ЮЖ>a.release();
ЮЖ>

Простите может я чего не понимаю, но в строке
s2.push_back(a.get());

a.get() передаст владение до того как push_back займется переаллокацией,
так что в этом случае auto_ptr никак на поможет при броске исключения,
нужен boost::shared_ptr.
Интересно, а boost::scoped_ptr можно ли тут использовить.
Re[3]: std:stack вызов деструктора
От: Анатолий Широков СССР  
Дата: 23.06.08 19:36
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Юрий Жмеренецкий, Вы писали:

А> Если при переаллокации памяти в push вылетит исключение, то утечет добавляемый объект. Как вариант, лечится так:
ЮЖ>>
ЮЖ>>std::auto_ptr<A> a(new A(1));
ЮЖ>>s2.push_back(a.get());
ЮЖ>>a.release();
ЮЖ>>

А>Простите может я чего не понимаю, но в строке
А>
s2.push_back(a.get());

А>a.get() передаст владение до того как push_back займется переаллокацией,
А>так что в этом случае auto_ptr никак на поможет при броске исключения,
А>нужен boost::shared_ptr.
А>Интересно, а boost::scoped_ptr можно ли тут использовить.

Ошибка в рассуждениях в том, что "get передает владение" — это не так. Владение передает release().
Следовательно, если будет выброшено исключение автоматический объект a заберет память выделенную под A1 и ничего криминального не произойдет. Если исключение выброшено не будет, то a сложит с себя обязанности по уничтожению вызовом a.release().
Re[2]: tring to joke
От: Vamp Россия  
Дата: 23.06.08 19:45
Оценка:
К>Храни в стеке не голые указатели, а умные.

Интересно, что голый противопоставлен умному. Вот я, например, бываю голым, но от этого не становлюсь менее умным...
Да здравствует мыло душистое и веревка пушистая.
Re[3]: std:stack вызов деструктора
От: Юрий Жмеренецкий ICQ 380412032
Дата: 23.06.08 22:13
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Юрий Жмеренецкий, Вы писали:

А> Если при переаллокации памяти в push вылетит исключение, то утечет добавляемый объект. Как вариант, лечится так:
ЮЖ>>
ЮЖ>>std::auto_ptr<A> a(new A(1));
ЮЖ>>s2.push_back(a.get());
ЮЖ>>a.release();
ЮЖ>>

А>Простите может я чего не понимаю, но в строке
А>
s2.push_back(a.get());

А>a.get() передаст владение до того как push_back займется переаллокацией,
get не передает владение

А>так что в этом случае auto_ptr никак на поможет при броске исключения,

Поможет, поскольку при возникновении исключения release не будет вызван, сл-но std::auto_ptr останется владельцем объекта у удалит его в деструкторе.

А>нужен boost::shared_ptr.

s2.push(boost::shared_ptr<A>(new A(88));

boost::shared_ptr решает эту проблему потому что:
Он будет сконструирован до переаллокации(ref_count = 1). При успешном завершении push ref_count будет равен 2. Потом будет удален временный объект, ref_count = 1 и объект останется жив(сохранили ссылку). При исключении увеличения счетчика ссылок не произойдет(так и будет равен еденице), соответственно в деструкторе временного объекта он достигнет 0 и объект будет удален.

Вот в этой строке:
boost::shared_ptr<A> p(new A());

существует подобная проблема, но она решается в конструкторе shared_ptr: После выделения памяти под А будет выделена пямять под счетчик ссылок, но в случае возникновения исключения, указатель(параметр конструктора) будет принудительно удален.
Т.е. выглядит это приблизительно так:

shared_ptr::shared_ptr(T* p)
{
  try
  {
    _pi = new sp_counted_impl(...);
  }catch(...)
  {
    delete p;
    throw;
  }
}


для "нормальной" работы с "голыми" указателями push должен выглядедеть приблизительно так же, либо его вызов надо оборачивать в try/cacth или иным способом гарантировать удаление(std::auto_ptr) при возникновении исключения.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.