-
11. Data: 2010-09-16 16:24:15
Temat: Re: Zagwozdka - wyjątek w konstruktorze?
Od: Michoo <m...@v...pl>
W dniu 16.09.2010 01:10, klops pisze:
> Odpowiadam, bo dotychczasowe odpowiedzi są raczej słabe...
>
> Gdy rzucasz wyjątek w konstruktorze, to:
> 1. Zmienne utworzone na stosie zostaną prawidłowo zlikwidowane.
> 2. Zmienne utworzone na stercie (new) nie zostaną usunięte.
>
> Aby zaradzić 2. należy używać inteligentnych wkaźników (lub czegoś
> podobnego) tworzonych na stosie, np. auto_ptr.
Dlaczego okłamujesz Wojciecha? (No chyba że to zwykła ignorancja a nie
zła wola? Ale lansowaleś się na kogoś mającego pojęcie o języku...)
Wracając do tematu - tak jak pisał Qrczak - obiekty będą zniszczone,
delete wywołane.
Krótki przykład:
#include <iostream>
using namespace std;
char tab[100];
struct Bar{
Bar(){cout <<"Bar"<<endl;}
~Bar(){cout <<"~Bar"<<endl;}
};
class Foo{
Bar b;
public: Foo(){cout <<"Foo"<<endl;throw 1;}
~Foo(){cout <<"~Foo"<<endl;}
static void * operator new (size_t size){
cout <<"new"<<endl;
return (Foo*)tab;
}
static void operator delete (void *p, size_t size)
{
cout <<"delete"<<endl;
}
};
main()
{
try{
Foo *f=new Foo();
}
catch(...){
cout <<"catch"<<endl;
}
}
--
Pozdrawiam
Michoo
-
12. Data: 2010-09-16 18:51:21
Temat: Re: Zagwozdka - wyjątek w konstruktorze?
Od: Bronek Kozicki <b...@s...net>
On 16/09/2010 12:28, badzio wrote:
> On 15 Wrz, 19:39, "Wojciech \"Spook\" Sura"<spook"mad@hatter"op.pl>
> wrote:
>> Mogę oczywiście rzucić wyjątkiem, ale - z tego, co wiem - rzucanie
>> wyjątkami w konstruktorze jest nieszczególnie radosnym pomysłem.
>
> W symbianie jest cos takiego jak konstruktor dwufazowy. Konstruktor
nie tylko w symbianie, ale w środowiskach które obsługują normalnie
wyjątki z odwijaniem stosum, nie trzeba tego stosować.
Posterowi polecam książki tego autora, bo widzę że ma braki w rozumieniu
wyjątków:
http://www.amazon.co.uk/Exceptional-C-Herb-Sutter/dp
/0201615622/
A za darmo : http://www.gotw.ca/gotw/
B.
-
13. Data: 2010-09-16 22:00:36
Temat: Re: Zagwozdka - wyjątek w konstruktorze?
Od: klops <k...@k...pl>
Sie troche pomyliłem... Powinno być tak:
#include <iostream>
#include <memory>
using namespace std;
char tab[100];
struct Bar{
Bar(){cout <<"Bar"<<endl;}
~Bar(){cout <<"~Bar"<<endl;}
};
class Foo{
std::auto_ptr<Bar> b;
public:
Foo() : b(new Bar())
{
cout <<"Foo"<<endl;
throw 1;
}
~Foo()
{
cout <<"~Foo"<<endl;
}
static void * operator new (size_t size)
{
cout <<"new"<<endl;
return (Foo*)tab;
}
static void operator delete (void *p, size_t size)
{
cout <<"delete"<<endl;
}
};
main()
{
try{
Foo *f=new Foo();
}
catch(...){
cout <<"catch"<<endl;
}
}
-
14. Data: 2010-09-16 22:40:20
Temat: Re: Zagwozdka - wyjątek w konstruktorze?
Od: Michoo <m...@v...pl>
W dniu 16.09.2010 09:19, klops pisze:
>
> Wracając do tematu, zastanów się nad tym (może bozia pozwoli dostrzec
> problem o którym wzmiankowałem...):
[...]
> Foo()
> {
> b = new Bar();
> cout <<"Foo"<<endl;
> throw 1;
[...]
> Dla podpowiedzi: b wyciekło...
To nie ma nic (poza lokalizacją) wspólnego z konstruktorem - błąd leży w
braku zwalniania zasobów przy opuszczaniu zakresu. Tu masz to samo a kod
jest rodem z C.
{
char *buf=malloc(100);
//...
if(cond)
return -1;
//...
free(buf);
return 0;
}
Standardowym podejściem w sytuacji gdy używamy "gołych" wskaźników i
wyjątków w jednym miejscu (nie tylko w konstruktorze) jest taki zapis:
Foo():b(0)
{
try
{
cout <<"Foo"<<endl;
//...
b=new Bar();
//...
throw 1;
//...
}
catch(...)
{
if(b)
delete b;
throw;
}
}
--
Pozdrawiam
Michoo
-
15. Data: 2010-09-17 06:49:30
Temat: Re: Zagwozdka - wyjątek w konstruktorze?
Od: Bronek Kozicki <b...@s...net>
On 16/09/2010 08:19, klops wrote:
> class Foo{
> Bar* b;
> public:
> Foo()
> {
> b = new Bar();
no, ładny klops. Goły wskaźnik właścicielem zasobów?!
B.
-
16. Data: 2010-09-17 11:00:45
Temat: Re: Zagwozdka - wyjątek w konstruktorze?
Od: Michoo <m...@v...pl>
W dniu 16.09.2010 17:46, klops pisze:
>> Standardowym podejściem w sytuacji gdy używamy "gołych" wskaźników i
>> wyjątków w jednym miejscu (nie tylko w konstruktorze) jest taki zapis:
>
> Jest coś takiego jak "zdobywanie zasobów jest inicjowaniem" i auto_ptr
> wspiera tą technikę. Prawidłowe rozwiązanie tego problemu jest takie:
Nie,nie,nie. Jeżeli używasz gołych wskaźników (przyczyny różne - np
posiadany już kod z nich korzysta) to trzeba się zabezpieczyć przed
problemami a nie twierdzić, że złe wyjątki ciekną pamięć.
Zgadza się, że poza szczególnymi przypadkami używanie gołych wskaźników
jest błędem.
--
Pozdrawiam
Michoo
-
17. Data: 2010-09-17 11:47:48
Temat: Re: Zagwozdka - wyjątek w konstruktorze?
Od: "Wojciech \"Spook\" Sura" <spook"mad@hatter"op.pl>
Dnia 16-09-2010 o 17:46:36 klops <k...@k...pl> napisał(a):
> Jest coś takiego jak "zdobywanie zasobów jest inicjowaniem" i auto_ptr
> wspiera tą technikę. Prawidłowe rozwiązanie tego problemu jest takie:
Można nawet prościej:
Foo::Foo()
{
b = null;
try
{
b = new Bar();
}
catch(...)
{
if (b != null)
delete b;
throw;
}
}
Chciałbym tylko przypomnieć, że pierwotny problem dotyczył instancji klasy
jako takiej, a nie jej pól :)
Jest jasne, że destruktor się nie wywoła, więc nie ma komu zwolnić pól
klasy i konstruktor powinien zdążyć posprzątać po sobie zanim przepuści
wyjątek dalej.
Pozdrawiam -- Spook.
--
! ._______. Warning: Lucida Console sig! //) !
! || spk || www.spook.freshsite.pl / _ """*!
! ||_____|| spook at op.pl / ' | ""!
! | ___ | tlen: spoko_ws gg:1290136 /. __/"\ '!
! |_|[]_|_| May the SOURCE be with you! \/) \ !