/ Forside / Teknologi / Udvikling / Java / Nyhedsindlæg
Login
Glemt dit kodeord?
Brugernavn

Kodeord


Reklame
Top 10 brugere
Java
#NavnPoint
molokyle 3688
Klaudi 855
strarup 740
Forvirret 660
gøgeungen 500
Teil 373
Stouenberg 360
vnc 360
pmbruun 341
10  mccracken 320
Destructor :-(
Fra : Martin Ehmsen


Dato : 24-03-02 18:41

Hej...

Jeg har er løbet ind i et problem (som jeg har løst , men det gav
anledning til undren over hvorfor klasser i Java ikke kan have
destructors som de kendes fra C++.
Den forklaring som man oftest støder ind i, er at destructors i C++
bruges til at frigøre hukommelse som ikke længere skal bruges. Dette
problem har man jo ikke i Java.
Men nu kan destructors også bruges til andet. Jeg havde fx et statisk
felt i en klasse, som blev opdateret når nye objekter af klassen blev
oprettet. Men samtidig ville jeg også gerne have feltet opdateret når
objekter blev nedlagt. I sådan en situation ville destructors være en
let løsning.
Man kunne selvfølgelig vælge at lægge koden i: protected void finalize()
Som så ville fungerer som en slags destructor, men finalize() bliver kun
kaldt når garbage collector'en har rydet op, og det er der jo ingen
garanti for hvornår den gør.
Jeg ville høre om der er andre som også har siddet med problemet og
hvordan I evt. løste det. Hvis der også er nogen som har en god
forklaring på hvorfor Java ikke har destructors, så vil jeg da også
gerne høre den.

Martin
--
Jeg har det med min rumlige frihed som jeg har lagt mærke til at mænd
har det med deres testikler.
Jeg vugger den som et spædbarn, og tilbeder den som en gudinde.
   Smilla Jaspersen

 
 
Kim Schulz (24-03-2002)
Kommentar
Fra : Kim Schulz


Dato : 24-03-02 18:58

On Sun, 24 Mar 2002 17:40:42 GMT
Martin Ehmsen <ehmsen@imada.sdu.dk> wrote:
> Hej...
>
> Jeg har er løbet ind i et problem (som jeg har løst , men det gav
> anledning til undren over hvorfor klasser i Java ikke kan have
> destructors som de kendes fra C++.
> Den forklaring som man oftest støder ind i, er at destructors i C++
> bruges til at frigøre hukommelse som ikke længere skal bruges. Dette
> problem har man jo ikke i Java.
> Men nu kan destructors også bruges til andet. Jeg havde fx et statisk
> felt i en klasse, som blev opdateret når nye objekter af klassen blev
> oprettet. Men samtidig ville jeg også gerne have feltet opdateret når
> objekter blev nedlagt. I sådan en situation ville destructors være en
> let løsning.
> Man kunne selvfølgelig vælge at lægge koden i: protected void
> finalize() Som så ville fungerer som en slags destructor, men
> finalize() bliver kun kaldt når garbage collector'en har rydet op, og
> det er der jo ingen garanti for hvornår den gør.
> Jeg ville høre om der er andre som også har siddet med problemet og
> hvordan I evt. løste det. Hvis der også er nogen som har en god
> forklaring på hvorfor Java ikke har destructors, så vil jeg da også
> gerne høre den.

du kan selv kalde garbage collectoren ved hjælp af en metode der svjh
ligger i System eller Runtime. Den hedder vist gc() eller noget i den
stil.

MVH
Kim Schulz

--
www.schulz.dk - En nørds bekendelser | All diplomacy is a
www.guadec.org - tapas, beer and gnome | continuation of war by other
| means. -- Chou En Lai

Kim Schulz (24-03-2002)
Kommentar
Fra : Kim Schulz


Dato : 24-03-02 19:02

On Sun, 24 Mar 2002 18:58:00 +0100
> du kan selv kalde garbage collectoren ved hjælp af en metode der svjh
> ligger i System eller Runtime. Den hedder vist gc() eller noget i den
> stil.

fandt den lige i API'et. Den hedder enten System.gc() eller
Runtime.getRuntime().gc().

alternativt findes der også en System.runFinalization() og
Runtime.getRuntime().runFinalization()

se omkring:
http://java.sun.com/j2se/1.4/docs/api/java/lang/System.html#runFinalization()

Der er flere metoder der som du vil kunne bruge!
MVH
Kim Schulz


--
www.schulz.dk - En nørds bekendelser | A mouse is an elephant built
www.guadec.org - tapas, beer and gnome | by the Japanese.
|

Flemming Jensen (24-03-2002)
Kommentar
Fra : Flemming Jensen


Dato : 24-03-02 19:54

On Sun, 24 Mar 2002 17:40:42 GMT, Martin Ehmsen <ehmsen@imada.sdu.dk>
wrote:

>... når objekter blev nedlagt ...

En del af forklaringen ligger faktisk i det du selv skriver, for
du forklarer nemlig bekvemt ikke hvad du forståer ved at et
"objekt bliver nedlagt". På en måde lyder det så enkelt, men når
man tænker over det, bliver det mere kompliceret.

Der er flere muligheder:

1. Et objekt bliver nedlagt når jeg siger det skal nedlægges

Så laver man blot en metode man kalder, der afvikler objektet,
frigiver dens resourcer og f.eks. ændre din instans-tæller.
Det er det der sker i f.eks. C++, hvor sproget dog gør det
bekvemmere ved at du ikke selv skal kalde destructoren i
nogle situationer (delete ... kan betragtes som et indirekte
kald af destructoren)

2. Et objekt bliver nedlagt så snart der ikke er nogen der
refererer til det.

Det er det indtryk mange får når de hører om garbage collectoren
i Java, men det er ikke sandt. Idéen med garbage collectoren er at
den rydder op når der ikke er andet at lave, eller når det er
strengt nødvendigt. Fordelen er at man ikke skal huske at bruge
delete ... som i C++, og at rigtige memory leaks derfor ikke
skulle kunne forekomme (memory leaks og den tid det tager at
debugge dem, koster utrolige summer)

Hvis Java eller et andet sprog skulle understøtte pkt. 2 ville
dette blive utrolig ineffektivt, og der er mig bekendt igen sprog
der arbejde med øjeblikkelig oprydning. Mange tror at en slags
reference-counter kan løse problemet, men de er meget ineffektive
og samtidig kommer de til kort i flere situationer - f.eks. i cykliske
strukturer.

Hold dig forøvrigt langt fra finalize og System.gc, de burde
aldrig have været indført i sproget. Der er ingen garanti for
at finalize nogensinde bliver udført, med mindre garbage collectoren
sletter objektet før programmet stopper. Ethvert kald af diverse
metoder der skal få garbage collectoren til at køre, overlader det
altid til garbage colletoren selv at beslutte om den vil. I det
hele taget er finalize meget vanskeligt at understøtte i
virtuelle maskiner og man har ikke fundet en løsning der er
bare nogenlunde effektiv, så finalize er en død sild!

Det er meget få situationer hvor man reelt har brug for en
destructor, og man bør i alle disse tilfælde i stedet lave en
metode der foretager den fornødne oprydning. I C++ skal man
selv rydde op i _mange_ flere situationer, og i dette sprog
er det derfor betydelig vigtige at have destructor-funktionalitet.

Dit eksempel med en destructor i C++ der tæller en statisk variabel
ned, så du hele tiden ved hvor mange instanser der eksisterer er
heller ikke holdbart hvis man glemmer delete ..., og hvis man skal
huske delete ..., for at det fungerer, kan man lige så godt selv
kalde en funktion på instansen der fungerer som destruktor.


/Flemming Jensen


Martin Ehmsen (24-03-2002)
Kommentar
Fra : Martin Ehmsen


Dato : 24-03-02 21:56

On Sun, 24 Mar 2002 18:53:32 GMT, Flemming Jensen <nospam@nospam.com> wrote:
[snip]

Tak for den fine gennemgang, det var sådan noget jeg ledte efter.
Jeg havde bare ikke lige overvejet at jeg faktisk selv havde givet
svaret
Du skulle vil ikke tilfældigvis ligge inde med et link til en gennemgang
af Java's GC og evt. også andre metoder til at lave GC på??
For det må jo egentligt ikke være helt så lige til at bestemme hvornår
man skal lave GC på runtime...

Martin
--
Jeg har det med min rumlige frihed som jeg har lagt mærke til at mænd
har det med deres testikler.
Jeg vugger den som et spædbarn, og tilbeder den som en gudinde.
   Smilla Jaspersen

Martin Moller Peders~ (24-03-2002)
Kommentar
Fra : Martin Moller Peders~


Dato : 24-03-02 23:25

In <slrna9seml.12d.ehmsen@v64me.tbt.kollegienet.dk> Martin Ehmsen <ehmsen@imada.sdu.dk> writes:

>On Sun, 24 Mar 2002 18:53:32 GMT, Flemming Jensen <nospam@nospam.com> wrote:
>[snip]

>For det må jo egentligt ikke være helt så lige til at bestemme hvornår
>man skal lave GC på runtime...

Derfor skal du overlade det 100% til JVM at bestemme. Det vil den goere
meget bedre end du kan.

/Martin

thomas (25-03-2002)
Kommentar
Fra : thomas


Dato : 25-03-02 00:50


"Martin Ehmsen" <ehmsen@imada.sdu.dk> wrote in message > Du skulle vil ikke
tilfældigvis ligge inde med et link til en gennemgang
> af Java's GC og evt. også andre metoder til at lave GC på??
> For det må jo egentligt ikke være helt så lige til at bestemme hvornår
> man skal lave GC på runtime...

På denne adresse er der et par gode artikler om GC:
http://www.javaworld.com/channel_content/jw-jvm-index.shtml

med venlig hilsen
Thomas




Jan Jonasen (25-03-2002)
Kommentar
Fra : Jan Jonasen


Dato : 25-03-02 20:04

Martin Ehmsen <ehmsen@imada.sdu.dk> wrote:

> Du skulle vil ikke tilfældigvis ligge inde med et link til en gennemgang
> af Java's GC og evt. også andre metoder til at lave GC på??
> For det må jo egentligt ikke være helt så lige til at bestemme hvornår
> man skal lave GC på runtime...
>
Du kan tage et kig på
<http://java.sun.com/docs/books/performance/1st_edition/html/JPAppGC.fm.
html#998394>

--
Mvh/re Jan Jonasen
jonasen (at) it (dot) dk

If I wanted culture, I'd eat yogurt.

Mogens Hansen (24-03-2002)
Kommentar
Fra : Mogens Hansen


Dato : 24-03-02 22:06


"Flemming Jensen" <nospam@nospam.com> wrote

[snip]
> I C++ skal man
> selv rydde op i _mange_ flere situationer, og i dette sprog
> er det derfor betydelig vigtige at have destructor-funktionalitet.
>
[snip]

Det er et almindeligt udsagn, som dog ikke bliver mere rigtigt af at blive
gentaget.
Hvis man koder fornuftigt i C++ skal man _meget_ sjældent selv kalde
"delete" - sproget sikrer det automatisk på et veldefineret tidspunkt.

Tag et simpelt eksempel, med frigivelse af resource fil-handle:

I C++ vil man skrive

void foo(const char* filename)
{
ifstream file(filename);
if(file) {
// read the file, and use the content
}
}

Når "file" ikke længere eksisterer (uanset årsag: foo returnerer, en
exception bliver smidt) bliver fil-handlet øjeblikkeligt frigivet.
Man skal _ikke_ selv gøre noget som helst for at sikre at det sker.

Venlig hilsen

Mogens Hansen



Flemming Jensen (24-03-2002)
Kommentar
Fra : Flemming Jensen


Dato : 24-03-02 23:20

On Sun, 24 Mar 2002 22:06:12 +0100, "Mogens Hansen"
<mogens_h@dk-online.dk> wrote:

>
>"Flemming Jensen" <nospam@nospam.com> wrote
>
>[snip]
>> I C++ skal man
>> selv rydde op i _mange_ flere situationer, og i dette sprog
>> er det derfor betydelig vigtige at have destructor-funktionalitet.
>>
>[snip]
>
>Det er et almindeligt udsagn, som dog ikke bliver mere rigtigt af at blive
>gentaget.
>Hvis man koder fornuftigt i C++ skal man _meget_ sjældent selv kalde
>"delete" - sproget sikrer det automatisk på et veldefineret tidspunkt.

Jeg programmerer ikke så meget C++ længere så jeg skal ikke påstå
jeg er specielt ekspert på området, men dit eksempel går lidt skævt
på spørgsmålet. Jeg ved godt at locals bliver automatisk destructed,
men locals er ikke karakteristisk for C++, det er det snarere for
C. ifstream findes naturligvis ikke i C, men ellers er det blot et
C-eksempel du viser med en global funktion.

>Tag et simpelt eksempel, med frigivelse af resource fil-handle:
>
>I C++ vil man skrive

Som sagt det er ikke "rigtig" et C++ eksempel

>void foo(const char* filename)
>{
> ifstream file(filename);
> if(file) {
> // read the file, and use the content
> }
>}
>
>Når "file" ikke længere eksisterer (uanset årsag: foo returnerer, en
>exception bliver smidt) bliver fil-handlet øjeblikkeligt frigivet.
>Man skal _ikke_ selv gøre noget som helst for at sikre at det sker.

Du kan ikke basere din OO-programmering i C++ på locals. Det virkelig
interessante er deallokering af datakernen, det er den der giver
problemerne.

locals allokeres på stakken og deres deallokering er blot en ændring
af stackpointeren. Mht. memory leaks er det allokeringer på heapen
der giver problemer.


/Flemming Jensen


Mogens Hansen (25-03-2002)
Kommentar
Fra : Mogens Hansen


Dato : 25-03-02 19:35


"Flemming Jensen" <nospam@nospam.com> wrote
>On Sun, 24 Mar 2002 22:06:12 +0100, "Mogens Hansen"
><mogens_h@dk-online.dk> wrote:
>
>>
>>"Flemming Jensen" <nospam@nospam.com> wrote
>>
>>[snip]
>>> I C++ skal man
>>> selv rydde op i _mange_ flere situationer, og i dette sprog
>>> er det derfor betydelig vigtige at have destructor-funktionalitet.
>>>
>>[snip]
>>
>>Det er et almindeligt udsagn, som dog ikke bliver mere rigtigt af at blive
>>gentaget.
>>Hvis man koder fornuftigt i C++ skal man _meget_ sjældent selv kalde
>>"delete" - sproget sikrer det automatisk på et veldefineret tidspunkt.
>
>Jeg programmerer ikke så meget C++ længere så jeg skal ikke påstå
>jeg er specielt ekspert på området, men dit eksempel går lidt skævt
>på spørgsmålet. Jeg ved godt at locals bliver automatisk destructed,
>men locals er ikke karakteristisk for C++, det er det snarere for
>C. ifstream findes naturligvis ikke i C, men ellers er det blot et
>C-eksempel du viser med en global funktion.
>

Jeg accepterer naturligvis at du ikke specielt er ekspert på området.
Jeg accepterer naturligvis også at denne diskution er lidt afsporet i
relation til Martin Ehmsen's oprindelige spørgsmål.
Du bragte noget forvirring omkring destructor og hvad man selv _skal_ gøre i
C++ på banen, og det korrigerede jeg.

Siden hvornår er destructorer blevet en del af C ?
Pointen i min kode var at C++ sproget garanterer at destructoren bliver
kaldt når "file" går ud af scope.
Det har _intet_ med C at gøre.

I C++ er destructor og explicit kald til "operator delete" uafhængige.
Destructoren kan sagtens køre, uden at "operator delete" bliver kaldt -
sådan som jeg viste i min kode.
"operator delete" kan også kaldes uden at der eksekveres nogen destructor
(for typer der ikke har en constructor, som f.eks. "int").
Destructorer rydder op på et objekts vegne og konverterer den plads objektet
fyldte til "raw memory" - hvad enten det er på heapen eller på stakken.
"operator delete" returnerer hukommelse (raw memory) som er allokeret med
"operator new" til heap manageren.

Det er forkert at sige at locals (automatic variable) ikke er karakteristisk
for C++ - det er blot ikke den eneste mulige form for allokering.
Automatic variable er f.eks. essentielle for programmerne ud fra et
korrektheds synpunkt i forbindelse med exceptions.
Kig på hvordan C++ Standard library klassen "std::auto_ptr" er beregnet til
at blive brugt, og du vil se at du tager fejl.
Vis mig een seriøs C++ bog, der ikke bruger automatic variable.
Vis mig eet velskrevet C++ program der ikke bruger automatic variable.

Hvad er der galt med en global funktion i C++ ?
Den er ligeså velberettiget som en member-funktion.

Generelt er det nemmest i C++, hvis man sikrer at allokeret hukommelse ejes
af noget, hvad enten det er eksekverings konteksten (på stakken) eller om
det er et andet objekt som et data medlem.

>>Tag et simpelt eksempel, med frigivelse af resource fil-handle:
>>
>>I C++ vil man skrive
>
>Som sagt det er ikke "rigtig" et C++ eksempel
>

Kan du være mere præcis med hvad du mener med at det ikke er et "rigtigt"
C++ eksempel ?
I henhold til hvilken anerkendt opfattelse af C++ er det ikke "rigtig" C++ i
relation til allokering af objekter og kald af destructor ?

Kender du C++ begrebet som Bjarne Stroustrup (designeren af C++ sproget)
kalder RAII (Resource Acquisition Is Initialization) ? Hvis du gør vil du
vide at automatic variable er en almindlig teknik i C++ til resource
allokering og frigivelse.
Mener du f.eks. at det ikke er en konstruktion som man ser i produktions C++
? I så fald tager du fejl.
Mener du at _kun_ member funktioner er "rigtig" C++ ? I så fald tager du
fejl - kig på C++ Standard Library, der er mange ikke member funktioner.


>>void foo(const char* filename)
>>{
>> ifstream file(filename);
>> if(file) {
>> // read the file, and use the content
>> }
>>}
>>
>>Når "file" ikke længere eksisterer (uanset årsag: foo returnerer, en
>>exception bliver smidt) bliver fil-handlet øjeblikkeligt frigivet.
>>Man skal _ikke_ selv gøre noget som helst for at sikre at det sker.
>
>Du kan ikke basere din OO-programmering i C++ på locals. Det virkelig
>interessante er deallokering af datakernen, det er den der giver
>problemerne.
>

Nej, men jeg kan i høj basere mig på at ethvert objekt har en veldefineret
ejer.
Det er ikke så svært endda:

int main(void)
{
DataKernel dk;
DoSomething(dk);
}

"dk" lever stort set lige så længe som programmet kører, og har ansvaret for
at oprette og nedlægge hele datakernen.
Sig ikke at det er en atypisk konstruktion. Sådan gør jeg i den virkelige
verden mod passende betaling.

>locals allokeres på stakken og deres deallokering er blot en ændring
>af stackpointeren.

Hvad med kald af constructor / destructor ?
Hvad med afvikling af exceptions ?

> Mht. memory leaks er det allokeringer på heapen
>der giver problemer.
>

Naturligvis skal man gøre rede for hvor man frigiver med "delete", når man
har skrevet "new".
Det nemmeste er at undlade at skrive "new" i applikationskode, og i stedet
indkapsle det i klasser sådan som det f.eks. er gjort i C++ Standard library
klasserne "std::string" og "std::vector".
Kombiner det med værktøjer, der verificerer at man gør tingene rigtigt og
man har ikke noget nævneværdigt problem.


Venlig hilsen

Mogens Hansen





Flemming Jensen (26-03-2002)
Kommentar
Fra : Flemming Jensen


Dato : 26-03-02 02:32

On Mon, 25 Mar 2002 19:34:37 +0100, "Mogens Hansen"
<mogens_h@dk-online.dk> wrote:

>Siden hvornår er destructorer blevet en del af C ?
>Pointen i min kode var at C++ sproget garanterer at destructoren bliver
>kaldt når "file" går ud af scope.
>Det har _intet_ med C at gøre.

Om vi taler memory leaks på grund af new/delete/destructor eller
malloc/free lagde jeg ikke så meget vægt på, problemet er
grundlæggende det samme, at huske at få det gjort.

>I C++ er destructor og explicit kald til "operator delete" uafhængige.
>Destructoren kan sagtens køre, uden at "operator delete" bliver kaldt -
>sådan som jeg viste i min kode.
>"operator delete" kan også kaldes uden at der eksekveres nogen destructor
>(for typer der ikke har en constructor, som f.eks. "int").

Der er selvfølgelig altid undtagelser i et sprog der indeholder f.eks.
primitive typer, men det ændrer ikke på den generelle sammenhæng
mellem delete og destruktorer. Det interessante er heapen, ikke
hvordan du kan bøje din implementation over i locals, og nøjes
med at anvende en del af sprog - en del som er ufarlig, mens du
lader som om den farlige del ikke findes - eller at den ikke er
et problem, bare vi lader være med at bruge den!

>Destructorer rydder op på et objekts vegne og konverterer den plads objektet
>fyldte til "raw memory" - hvad enten det er på heapen eller på stakken.

Jeg tror ikke det betyder så meget at et objekt på stakken bliver raw
memory på grundlag af destructoren. Stackpointeren gør alligevel det
onde ved den når activationframen dør.

>"operator delete" returnerer hukommelse (raw memory) som er allokeret med
>"operator new" til heap manageren.
>
>Det er forkert at sige at locals (automatic variable) ikke er karakteristisk
>for C++ - det er blot ikke den eneste mulige form for allokering.

locals er ikke karakteristiske for C++ fordi dét der karakteriserer
C++ i forhold til C er objekter. locals findes både i C og C++, derfor
er de ikke karakteristiske for C++!

>Automatic variable er f.eks. essentielle for programmerne ud fra et
>korrektheds synpunkt i forbindelse med exceptions.
>Kig på hvordan C++ Standard library klassen "std::auto_ptr" er beregnet til
>at blive brugt, og du vil se at du tager fejl.
>Vis mig een seriøs C++ bog, der ikke bruger automatic variable.
>Vis mig eet velskrevet C++ program der ikke bruger automatic variable.

Nu må du rette mig hvis jeg tager fejl, men jeg
mener at huske, at en af de store grimmerter ved C++ er at exceptions
ikke rydder op efter sig, og dermed laver memory leaks. Ved kun at
bruge locals er det naturligvis ikke noget problem, men det vi snakker
om er C++ ikke C-- (dvs. C++ minus alt hvad der kan give problemer)

>Hvad er der galt med en global funktion i C++ ?

Det samme som der er galt med globale funktioner i et hvilket som
helst andet sprog der bør efterlades i det netop afsluttede
århundrede. De kobler til højre og venstre og forurener det globale
navnerum.

>Den er ligeså velberettiget som en member-funktion.

Jeg er fuldstændig uenig

>Generelt er det nemmest i C++, hvis man sikrer at allokeret hukommelse ejes
>af noget, hvad enten det er eksekverings konteksten (på stakken) eller om
>det er et andet objekt som et data medlem.

Det er rigtig at det "er det nemmeste" - men det er ikke nemt. C++ er
for dem der har programmeret i mange år, og er up to date med de
seneste lapper ("patches" til ens programmeringsstil) der skal rede en
fra de faldgrubbe der er.

>>>Tag et simpelt eksempel, med frigivelse af resource fil-handle:
>>>
>>>I C++ vil man skrive
>>
>>Som sagt det er ikke "rigtig" et C++ eksempel
>>
>
>Kan du være mere præcis med hvad du mener med at det ikke er et "rigtigt"
>C++ eksempel ?
>I henhold til hvilken anerkendt opfattelse af C++ er det ikke "rigtig" C++ i
>relation til allokering af objekter og kald af destructor ?

Det er ikke et "rigtigt" C++ eksempel fordi det ikke er en member-
funktion der arbejder med en datakerne som vi på et tidspunkt skal
have destructed. Mao. det er et eksempel som snakker udenom problemet!

>Kender du C++ begrebet som Bjarne Stroustrup (designeren af C++ sproget)
>kalder RAII (Resource Acquisition Is Initialization) ? Hvis du gør vil du
>vide at automatic variable er en almindlig teknik i C++ til resource
>allokering og frigivelse.

Teknikken er et idiom man har fundet til at lappe på problemet.
Idéen med at indkapsle pointere i obejkter og gøre dem til locals, er
naturligvis en idé, men det er symptombehandling. Man kan ikke gøre
alt til locals uden at skulle bøje ryggen adskillige gange, og på
den måde at prøve at liste pointere ud af sproget er en kapitulation.
Pointere er problemet, så indkapsler vi pointere - en god idé, men
pointere er en del af sproget, så problemet er ikke væk!

>Mener du f.eks. at det ikke er en konstruktion som man ser i produktions C++
>? I så fald tager du fejl.

Det er sikkert en konstruktion man ser i produktionen men at man er
begrænset til denne konstruktion er som at færdes i et minefelt, man
skal bare passe på, og arbejde sig systematisk frem så er det ganske
ufarligt. Min pointe drejer sig ikke om, om man kan undgå memory leaks
i C++, men at man skal gøre sig betydelige anstrengelser, f.eks. i
form af at tillægge sig en bestemt programmerinsstil, som er en
indsnævring i forhold til det naturlige (hvad det så end er, man
kan jo vende sig til at det nødvendige er det naturlige)

>Mener du at _kun_ member funktioner er "rigtig" C++ ? I så fald tager du
>fejl - kig på C++ Standard Library, der er mange ikke member funktioner.

Jeg regner ikke nødvendigvis STL for at være "rigtig" C++. Hvis det
ikke er objektorinteret kan det være lige så meget standard som det
vil, det vil alligevel være usundt.

>Nej, men jeg kan i høj basere mig på at ethvert objekt har en veldefineret
>ejer.
>Det er ikke så svært endda:
>
>int main(void)
>{
> DataKernel dk;
> DoSomething(dk);
>}
>
>"dk" lever stort set lige så længe som programmet kører, og har ansvaret for
>at oprette og nedlægge hele datakernen.
>Sig ikke at det er en atypisk konstruktion. Sådan gør jeg i den virkelige
>verden mod passende betaling.

Du vedligeholder det sikkert også mod passende betaling

Du kan ikke for alvor mene at du allokerer hele dit objektsystem fra
main!

>>locals allokeres på stakken og deres deallokering er blot en ændring
>>af stackpointeren.
>
>Hvad med kald af constructor / destructor ?
>Hvad med afvikling af exceptions ?

Uvæsentligt - min pointe var at locals ikke er noget problem, og at
en snak om locals er at snakke udenom problemet. Naturligvis forsøger
man at gøre alle objekter til locals for så er problemet væk, men
det er en teknisk øvelse det ikke kan være meningen, at man skal
belaste programmørerne med. Idéen om at C++ er et ganske glimrende
sprog, hvis man bare programmerer på en nøje fastlagt måde er ren
til grin. Sproget er som det er, og hvis det ikke kan tåle at man
bruger det som sådan, burde man lavet et nyt.

>> Mht. memory leaks er det allokeringer på heapen
>>der giver problemer.
>>
>
>Naturligvis skal man gøre rede for hvor man frigiver med "delete", når man
>har skrevet "new".
>Det nemmeste er at undlade at skrive "new" i applikationskode, og i stedet
>indkapsle det i klasser sådan som det f.eks. er gjort i C++ Standard library
>klasserne "std::string" og "std::vector".
>Kombiner det med værktøjer, der verificerer at man gør tingene rigtigt og
>man har ikke noget nævneværdigt problem.

Du kan ikke afskrive en del af C++ (new/delete) og skubbe det over i
STL. At der er en række nyttige klasser i STL kan ikke betyde at
sproget nu ikke længere har et problem. Det er meget karakteristisk at
C++'s problemer skal løses med sindrige regler og konstruktioner,
i stedet for at lave sproglige tiltag der løser problemerne. C++ er
simpelthen så indklistreret i kompatibilitet med tidligere versioner
at lapperne bliver mere og mere komplicerede som tiden går.

Jeg ved godt at der findes mange smarte og sindrigt udtænkte måder
at undgå memory leaks på, men er problemet ikke at det er nødvendigt
med den slags tiltag? Hvis memory leaks ikke var så stort et problem
i C++, var løsningerne ved heller ikke så komplicerede (Man kan
naturligvis altid diskutere hvad der er "kompliceret", og for den
der kender disse løsninger, og for dig der bruger dem dagligt, er
de naturligvis ikke komplicerede. Men set i forhold til en gammel-dags
programmerinsstil hvor man bare havde og huske at rydde op efter sig,
så er det en komplikation)

Mao. der findes medicin der til dels kan kurere problemet med memory
leaks i C++, men jeg tager kun medicin når jeg er syg!


/Flemming Jensen


Mogens Hansen (26-03-2002)
Kommentar
Fra : Mogens Hansen


Dato : 26-03-02 06:48


"Flemming Jensen" <nospam@nospam.com> wrote in message
news:3c9fbf20.41906378@news.cybercity.dk...
> On Mon, 25 Mar 2002 19:34:37 +0100, "Mogens Hansen"
> <mogens_h@dk-online.dk> wrote:
>
> >Siden hvornår er destructorer blevet en del af C ?
> >Pointen i min kode var at C++ sproget garanterer at destructoren bliver
> >kaldt når "file" går ud af scope.
> >Det har _intet_ med C at gøre.
>
> Om vi taler memory leaks på grund af new/delete/destructor eller
> malloc/free lagde jeg ikke så meget vægt på, problemet er
> grundlæggende det samme, at huske at få det gjort.
>

Hvad var det i mit eksempel, som man skal huske at få gjort i relation til
frigivelse af resourcer ? (hint: intet)

Du forstår åbenbart ikke at der er en væsentlig forskel på new/delete og
destructor. Find en god bog (f.eks. "The C++ Programming Language, Special
Edtion", Bjarne Stroustrup) hvis du vil vide mere.
Hvor kommer malloc/free ind i billedet i denne snak ?
I relation til mit oprindelige eksempel bør det nærmere være fopen/fclose.
Det interesante er resource håndtering generelt - ikke memory resourcer
specifikt.

>
> Der er selvfølgelig altid undtagelser i et sprog der indeholder f.eks.
> primitive typer, men det ændrer ikke på den generelle sammenhæng
> mellem delete og destruktorer.

Igen få fat på en god bog, der beskriver sammenhængen mellem

>
> >Destructorer rydder op på et objekts vegne og konverterer den plads
objektet
> >fyldte til "raw memory" - hvad enten det er på heapen eller på stakken.
>
> Jeg tror ikke det betyder så meget at et objekt på stakken bliver raw
> memory på grundlag af destructoren. Stackpointeren gør alligevel det
> onde ved den når activationframen dør.
>

Hvad har det med tro at gøre ?
Lær det udenad!

>
> locals er ikke karakteristiske for C++ fordi dét der karakteriserer
> C++ i forhold til C er objekter. locals findes både i C og C++, derfor
> er de ikke karakteristiske for C++!

Du har en mærkværdig opfattelse af C++.
Indrøm bare at du ikke kan lide det og at du ikke kender det.

>
> >Automatic variable er f.eks. essentielle for programmerne ud fra et
> >korrektheds synpunkt i forbindelse med exceptions.
> >Kig på hvordan C++ Standard library klassen "std::auto_ptr" er beregnet
til
> >at blive brugt, og du vil se at du tager fejl.
> >Vis mig een seriøs C++ bog, der ikke bruger automatic variable.
> >Vis mig eet velskrevet C++ program der ikke bruger automatic variable.
>
> Nu må du rette mig hvis jeg tager fejl, men jeg
> mener at huske, at en af de store grimmerter ved C++ er at exceptions
> ikke rydder op efter sig, og dermed laver memory leaks.

Ok. Jeg retter dig. Det er absolut forkert.

> Ved kun at
> bruge locals er det naturligvis ikke noget problem, men det vi snakker
> om er C++ ikke C-- (dvs. C++ minus alt hvad der kan give problemer)
>

Du kender tydeligvis ikke C++ særligt godt, hvilket er helt i orden, hvis
blot du ikke udtaler dig om det.

> >Hvad er der galt med en global funktion i C++ ?
>
> Det samme som der er galt med globale funktioner i et hvilket som
> helst andet sprog der bør efterlades i det netop afsluttede
> århundrede. De kobler til højre og venstre og forurener det globale
> navnerum.
>

Objekter har sin beretigelse til noget.
Templates har sin beretigelsen til noget.
Ikke member funktion funktioner har sin beretigelse.

> >Den er ligeså velberettiget som en member-funktion.
>
> Jeg er fuldstændig uenig
>

Vi bliver nok overhovedet ikke enige, så det er nok ikke umagen værd.

> >Generelt er det nemmest i C++, hvis man sikrer at allokeret hukommelse
ejes
> >af noget, hvad enten det er eksekverings konteksten (på stakken) eller om
> >det er et andet objekt som et data medlem.
>
> Det er rigtig at det "er det nemmeste" - men det er ikke nemt. C++ er
> for dem der har programmeret i mange år, og er up to date med de
> seneste lapper ("patches" til ens programmeringsstil) der skal rede en
> fra de faldgrubbe der er.
>

Byg du bare dine egne fordomme op, som forhindrer dig i at lære nye ting.

> >Kender du C++ begrebet som Bjarne Stroustrup (designeren af C++ sproget)
> >kalder RAII (Resource Acquisition Is Initialization) ? Hvis du gør vil du
> >vide at automatic variable er en almindlig teknik i C++ til resource
> >allokering og frigivelse.
>
> Teknikken er et idiom man har fundet til at lappe på problemet.
> Idéen med at indkapsle pointere i obejkter og gøre dem til locals, er
> naturligvis en idé, men det er symptombehandling. Man kan ikke gøre
> alt til locals uden at skulle bøje ryggen adskillige gange, og på
> den måde at prøve at liste pointere ud af sproget er en kapitulation.
> Pointere er problemet, så indkapsler vi pointere - en god idé, men
> pointere er en del af sproget, så problemet er ikke væk!
>

Det er ikke memory - det er resource generelt.
Det er ikke automatic variable specifikt. Det er at have et vedstyret
ejerskab generelt, hvadenten det er som automatic variable eller som data
medlemmer i en klasse.

>
> >Mener du at _kun_ member funktioner er "rigtig" C++ ? I så fald tager du
> >fejl - kig på C++ Standard Library, der er mange ikke member funktioner.
>
> Jeg regner ikke nødvendigvis STL for at være "rigtig" C++. Hvis det
> ikke er objektorinteret kan det være lige så meget standard som det
> vil, det vil alligevel være usundt.
>

Ok. Så slap du katten ud af sækken.
Du er af den opfattelse at det objektorienterede paradigme er det eneste
sunde. Det er et fattigt verdenssyn.
Du ved simpelt hen ikke hvad moderne C++ er. Fair nok, men så lad være med
at udtale dig om det.

>
> Du vedligeholder det sikkert også mod passende betaling
>

Ja, da.
Hvis et program er nyttigt skal det vedligeholdes, så det modtager jeg gerne
betaling for.

> Du kan ikke for alvor mene at du allokerer hele dit objektsystem fra
> main!
>

Ansvaret for initialisering og nedlæggelse af hele mit objektsystem styres
fra main.
Tænk over det lidt. Det følger eksakt programmets behov.

> Uvæsentligt - min pointe var at locals ikke er noget problem, og at
> en snak om locals er at snakke udenom problemet. Naturligvis forsøger
> man at gøre alle objekter til locals for så er problemet væk, men
> det er en teknisk øvelse det ikke kan være meningen, at man skal
> belaste programmørerne med. Idéen om at C++ er et ganske glimrende
> sprog, hvis man bare programmerer på en nøje fastlagt måde er ren
> til grin.

Ethvert sprog har sin stil og idioms, som man skal kende og udnytte hvis man
skal bruge det effektivt.

> Jeg ved godt at der findes mange smarte og sindrigt udtænkte måder
> at undgå memory leaks på, men er problemet ikke at det er nødvendigt
> med den slags tiltag? Hvis memory leaks ikke var så stort et problem
> i C++, var løsningerne ved heller ikke så komplicerede (Man kan
> naturligvis altid diskutere hvad der er "kompliceret", og for den
> der kender disse løsninger, og for dig der bruger dem dagligt, er
> de naturligvis ikke komplicerede. Men set i forhold til en gammel-dags
> programmerinsstil hvor man bare havde og huske at rydde op efter sig,
> så er det en komplikation)
>

Prøv helt objektivt at forklare mig, og andre læsere af denne tråd, hvad der
er kompliceret i relation til resource styring ved at skrive:

void foo(void)
{
string text("hello world");
cout < text;
}


Venlig hilsen

Mogens Hansen



Flemming Jensen (29-03-2002)
Kommentar
Fra : Flemming Jensen


Dato : 29-03-02 21:56

On Tue, 26 Mar 2002 06:47:33 +0100, "Mogens Hansen"
<mogens_h@dk-online.dk> wrote:

>Hvad var det i mit eksempel, som man skal huske at få gjort i relation til
>frigivelse af resourcer ? (hint: intet)

Jeg prøver at nævne det igen. Dit eksempel er ikke dækkende for
C++, det begrænser sig i for høj grad ved kun at bruge locals.

>Du forstår åbenbart ikke at der er en væsentlig forskel på new/delete og
>destructor. Find en god bog (f.eks. "The C++ Programming Language, Special
>Edtion", Bjarne Stroustrup) hvis du vil vide mere.

Jeg har 2nd. ed., 3rd. ed. og senest special ed., og jeg har ikke
købt dem i går!

>Hvor kommer malloc/free ind i billedet i denne snak ?
>I relation til mit oprindelige eksempel bør det nærmere være fopen/fclose.
>Det interesante er resource håndtering generelt - ikke memory resourcer
>specifikt.

Det drejer sig ikke om en diskussion af tekniske forskelle mellem
new, delete, destructorer etc. Det drejer sig om at der er et
element af C++ der i praktis giver problemer. Nemlig at huske at
slette objekter, så vi ikke får memory leaks. Oprindelig betragtede
man det ikke som noget problem, fordi det i bund og grund er en
programmeringsfejl at glemme det. Men er der tilstrækkelig
mange programmører der har problemet, bliver det også sprogets
problem, og det er det der er grunden til at man overhovedet
diskuterer det.

>> >Destructorer rydder op på et objekts vegne og konverterer den plads
>objektet
>> >fyldte til "raw memory" - hvad enten det er på heapen eller på stakken.
>>
>> Jeg tror ikke det betyder så meget at et objekt på stakken bliver raw
>> memory på grundlag af destructoren. Stackpointeren gør alligevel det
>> onde ved den når activationframen dør.
>>
>
>Hvad har det med tro at gøre ?
>Lær det udenad!

Så lad mig formulere det på en anden måde. Det er stackpointeren der
bestemmer hvad der er raw memory på stakken, din betragtning om at
det er destructoren der returnerer objekter på stacken til raw
memory er sludder. Eller vi taler ikke om det samme når vi siger
raw memory (en betegnelse jeg nok kun vil bruge vedrørende heapen).
Eller jeg er måske ikke helt med på hvad du skriver - tænker du på
de objekter der ligger på heapen som bliver til raw mem gennem at
der er objekter på stakken der bliver destructed?

>> locals er ikke karakteristiske for C++ fordi dét der karakteriserer
>> C++ i forhold til C er objekter. locals findes både i C og C++, derfor
>> er de ikke karakteristiske for C++!
>
>Du har en mærkværdig opfattelse af C++.
>Indrøm bare at du ikke kan lide det og at du ikke kender det.

Hvis du betegner de tre linier jeg har skrevet ovenfor som
"mærkværdige" vil jeg gerne høre hvorfor du har valgt at
bruge C++. Da jeg startede med at anvende C++ i 1986 var
det fordi det var det bedste kommercielle objektorienterede
sprog (i 80'erne), og grunden til at jeg ikke anvender det længere
er at denne forudsætning ikke længere holder.

>> Nu må du rette mig hvis jeg tager fejl, men jeg
>> mener at huske, at en af de store grimmerter ved C++ er at exceptions
>> ikke rydder op efter sig, og dermed laver memory leaks.
>
>Ok. Jeg retter dig. Det er absolut forkert.

Gælder det også hvis jeg i starten af en try-blok allokerede et
objekt på heapen som jeg vil deallokerer i slutningen af blokken,
men der kastes en exception inden da, og jeg kun har fat i objektet
med en pointer som er erklæret i try-blokken.

>Du kender tydeligvis ikke C++ særligt godt, hvilket er helt i orden, hvis
>blot du ikke udtaler dig om det.

Hvad skal jeg sige til det?

>Ikke member funktion funktioner har sin beretigelse.

I et funktionelt programmeringssprog, men det er C++ ikke, derfor
er mit svar: Nej!

>Vi bliver nok overhovedet ikke enige, så det er nok ikke umagen værd.

Nej, sikkert ikke, men nu skriver jeg primært også i denne tråd af
hensyn til de andre der formodentlig også læser den - jeg har
for længst opgivet at "frelse" dig

Mit gennerelle indtryk er, at du ser verden fra C++ og ud, mens jeg
_prøver_ at se udefra og ind i C++.

>Byg du bare dine egne fordomme op, som forhindrer dig i at lære nye ting.

Jeg lærer noget nyt hele tiden. F.eks. har jeg fået en _bedre_
forståelse af at undgå memory leaks igennem denne tråd, men på
trods af det synes jeg stadig at jeg skal binde den ene "C++-arm" på
ryggen for at bruge "locals-lappen". Det bliver ikke kun et
sprøgrsmål om en sund programmerinsgstil, men et spørgsmål om at
jeg skal betragte visse dele af sproget som deprecated; hvilket bliver
C--.

>Det er ikke memory - det er resource generelt.

(I en face to face diskussion kan man beskrive tingene mere udførligt,
i en post gør man det lidt kortere) Det gælder naturligvis også
resourcer generelt, hvilket er grunden til at Java ikke bare klarer
frisag med en garbage collector og det forkvaklede finalize (så nemt
er det trods alt ikke at løse disse problemer).

>Det er ikke automatic variable specifikt. Det er at have et vedstyret
>ejerskab generelt, hvadenten det er som automatic variable eller som data
>medlemmer i en klasse.

I ethvert realistisk objektsystem findes der objekter der ikke er
aggregeret andre objekter (ejet af), og en løsning der kræver at
alle objekter er aggregeret, er for vidtgående i forhold til den
indflydelse et sprog skal have på objektmodellen (nemlig ingen!)

>> Jeg regner ikke nødvendigvis STL for at være "rigtig" C++. Hvis det
>> ikke er objektorinteret kan det være lige så meget standard som det
>> vil, det vil alligevel være usundt.
>>
>Ok. Så slap du katten ud af sækken.
>Du er af den opfattelse at det objektorienterede paradigme er det eneste
>sunde. Det er et fattigt verdenssyn.

Jeg mener ikke at det objektorienterde paradigme er det eneste sunde
paradigme, men det er det eneste sunde paradigme man med rimelig kan
anvende C++ til. Til andre sunde paradigmer (funktionelle, logiske
etc. findes langt mere målrettede sprog, multiparadigmiske sprog
er en misforståelse af hvilket forhold der skal være mellem et
sprog og et paradigme)

>Du ved simpelt hen ikke hvad moderne C++ er. Fair nok, men så lad være med
>at udtale dig om det.

"Moderne C++" - Hvad er det for en betegnelse? C++ er C++.
Hvad er umoderne C++? Er der dele af sproget som det er umoderne
at bruge eller er "moderne C++" bare en betegnelse for den seneste
programmeringsstil man skal tillægge sig hvis man skal undgå
problemer. Hvorfor skal programmørerne løse sprogets problemer?

Mig bekendt arbejder man ikke med betegnelsen "deprecated" i
forbindelse med hverken C++ eller andre sprog (bemærk at jeg taler om
_sproget_), så ville det være dets egen nekrolog. Hvis man har høstet
erfaringer i retning af at der er sproglige konstruktioner i et sprog
der er usunde at bruge, så lav et nyt sprog - ikke en ny
programmeringsstil i sproget!

>Ansvaret for initialisering og nedlæggelse af hele mit objektsystem styres
>fra main.
>Tænk over det lidt. Det følger eksakt programmets behov.

Jeg tror du kommer til at give mig et hint mere. Det eneste behov vi
har for main er at få skubbet programmet forbi det punkt hvor der
endnu ikke findes objekter.

>Ethvert sprog har sin stil og idioms, som man skal kende og udnytte hvis man
>skal bruge det effektivt.

Det er rigtigt, men idiomer skal ikke løse problemer der burde være
løst den dag sproget blev designet (Det er kun hypotetisk at de burde
være løst da sproget blev designet, man kan naturligvis ikke forudse
alle problemer der vil komme, efterhånden som sproget modnes. Det
er også derfor man med ca. 10 års mellemrum bør smide et sprog væk
og lave et nyt)

>Prøv helt objektivt at forklare mig, og andre læsere af denne tråd, hvad der
>er kompliceret i relation til resource styring ved at skrive:
>
>void foo(void)
>{
> string text("hello world");
> cout < text;
>}

Meget simpelt eksempel, der skalerer dårligt. Jeg kan ikke se dette
eksempel har fortsat relevans. Det er to linier kode, hvor du laver en
local der naturligvis ikke giver problemer. Din pointe synes hele
tiden at være: "Se, jeg laver en local, der er ikke noget problem",
min pointe er "Se du laver _kun_ en local, skal vi prøve at lave lidt
mere C++ end det?".

Problemet er ikke hvordan det fungerer med et par linier kode og
et par objekter. Jeg har vanskeligere ved at se det som en simpel
løsning hvis vi taler om objektsystemer med _mange_ objekter.
Problemet er ikke at løsningen ikke virker, men at den skaffer os af
med et problemer og giver os et nyt, nemlig at skulle begrænse os til
til locals og til disse's aggregering objekter.

Hvis moderne C++ er "C++ hvor vi gør alt hvad vi kan for kun at bruge
locals og aggregerede objekter (objekter der ejes af nogen)", så er
moderne C++ kun et spørgsmål om at lave C++ der kan fungere "på
trods af at det er skrevet i C++".

Min holdning til C++: Det er et sprog der virkelig har bidraget
til udviklingen af objektorientering, men at det har overlevet sig
selv - Bjarne skulle lave et nyt sprog, i stedet for at overlade
det til andre - pyt med at det ikke kan sælges!

Min holdning til Java: Det er et sprog der har fornyet sig i forhold
til C++, ca. 25% fornyelse i forhold til hvad det burde have gjort,
hvilket helt sikkert skyldes at det ville være meget vanskelige at
sælge sproget hvis det virkelig gjorde op med f.eks. C-syntaksen,
og hvad det ellers har slæbt med ind fra C++. (F.eks. ud med alle
primitive datatyper - de skal være objekter)

(Jeg skal understrege at de to nævnte holdninger er rettet mod
denne tråd, set i en større sammenhæng kræver det naturligvis en
mere nuanceret beskrivelse. Vi diskuterer trods alt kun et snævert
hjørne af C++/Java)

Alle kommercielle sproglige succeser indenfor objektorienterede sprog
er kendetegnet ved at de danser omkring C. Sprog som: Smalltalk,
Beta og Eiffel er på mange måder mere interessante, men det er
tydeligt hvorfor de har det så svært - vi har ikke råd til at
sætte alle vores C-programmører et par år på skolebænken. Sådan
er realiteterne og det må vi naturligvis leve med, bare vi
bevæger os i den rigtige retning; hvilket pt. er den objekt-
orienterede retning (der kommer sikkert noget bedre engang i
fremtiden, eller måske et revival af et ældre paradigme (det
funktionelle?))


/Flemming Jensen


Mogens Hansen (30-03-2002)
Kommentar
Fra : Mogens Hansen


Dato : 30-03-02 13:23


"Flemming Jensen" <nospam@nospam.com> wrote in message
news:3ca4ba08.1276775@news.cybercity.dk...
> On Tue, 26 Mar 2002 06:47:33 +0100, "Mogens Hansen"
> <mogens_h@dk-online.dk> wrote:
>
> >Hvad var det i mit eksempel, som man skal huske at få gjort i relation
til
> >frigivelse af resourcer ? (hint: intet)
>
> Jeg prøver at nævne det igen. Dit eksempel er ikke dækkende for
> C++, det begrænser sig i for høj grad ved kun at bruge locals.
>
> >Du forstår åbenbart ikke at der er en væsentlig forskel på new/delete og
> >destructor. Find en god bog (f.eks. "The C++ Programming Language,
Special
> >Edtion", Bjarne Stroustrup) hvis du vil vide mere.
>
> Jeg har 2nd. ed., 3rd. ed. og senest special ed., og jeg har ikke
> købt dem i går!
>

Udemærket, men det er ikke tilstrækkeligt at købe dem.
Det væsentlige er at man læser og forstår dem.
Den væsentlige forskel mellem "Third Edition" (fra før foråret 2000) og
"Special Edition" er appendix D (Locales) og appendix E (Standard Library
Exception Safety).

Du kan umuligt have læst og forstået appendix E, når du tidligere i denne
tråd skrev:
<citat>
Nu må du rette mig hvis jeg tager fejl, men jeg mener at huske, at en af de
store grimmerter ved C++ er at exceptions ikke rydder op efter sig, og
dermed laver memory leaks.
<citat/>

Hvis du er i tvivl om hvorvidt jeg har læst og _forstået_ Appendix D og
Appendix E, så kig på
http://www.research.att.com/~bs/3rd_loc0.html
http://www.research.att.com/~bs/3rd_safe0.html
Der er _ikke_ tale om navne sammenfald.

Det er uvæsentligt i denne sammenhæng (og de fleste andre sammenhænge,
bortset fra historiske), men jeg har _også_ "First Edition".

> >Hvor kommer malloc/free ind i billedet i denne snak ?
> >I relation til mit oprindelige eksempel bør det nærmere være
fopen/fclose.
> >Det interesante er resource håndtering generelt - ikke memory resourcer
> >specifikt.
>
> Det drejer sig ikke om en diskussion af tekniske forskelle mellem
> new, delete, destructorer etc.

Skelnen _er_ vigtigt, hvis man skal snakke om resouce leaks.
Mangle kald til "delete" giver resource leaks, og det har egentlig ikke
noget med destructorer at gøre.

> Det drejer sig om at der er et
> element af C++ der i praktis giver problemer. Nemlig at huske at
> slette objekter, så vi ikke får memory leaks. Oprindelig betragtede
> man det ikke som noget problem, fordi det i bund og grund er en
> programmeringsfejl at glemme det. Men er der tilstrækkelig
> mange programmører der har problemet, bliver det også sprogets
> problem, og det er det der er grunden til at man overhovedet
> diskuterer det.
>

Enig.
Det er derfor der er brug for oplysning og undervisning, sådan som jeg har
forsøgt i denne tråd. Det kræver naturligvis at budskabet bliver forklaret
tilstrækkeligt godt, og modtagerne er villige og i stand til at lytte og
forstå.
Det vigtigste er: "den nemmeste måde at undgå leak i C++ er at lade være med
at lave dem".
Det er derfor C++ Standard Library klasser som "std::string", "std::vector"
og "std::auto_ptr" er vigtige.
Det er derfor værktøjer (som f.eks. NuMega BoundsChecker, Rational Purify og
Borland CodeGuard), som under udviklinger checker for klassiske C og C++
fejl (som resource leaks, access to freed memroy, buffer overrun etc.) er
vigtige.

Der er flere myter om problemer med leaks i C++ end der er reele problemer.

> >> >Destructorer rydder op på et objekts vegne og konverterer den plads
> >objektet
> >> >fyldte til "raw memory" - hvad enten det er på heapen eller på
stakken.
> >>
> >> Jeg tror ikke det betyder så meget at et objekt på stakken bliver raw
> >> memory på grundlag af destructoren. Stackpointeren gør alligevel det
> >> onde ved den når activationframen dør.
> >>
> >
> >Hvad har det med tro at gøre ?
> >Lær det udenad!
>
> Så lad mig formulere det på en anden måde. Det er stackpointeren der
> bestemmer hvad der er raw memory på stakken, din betragtning om at
> det er destructoren der returnerer objekter på stacken til raw
> memory er sludder. Eller vi taler ikke om det samme når vi siger
> raw memory (en betegnelse jeg nok kun vil bruge vedrørende heapen).
> Eller jeg er måske ikke helt med på hvad du skriver - tænker du på
> de objekter der ligger på heapen som bliver til raw mem gennem at
> der er objekter på stakken der bliver destructed?
>

Raw memory (eller mere korrekt raw storage) betyder i relation til C++
uinitialiseret hukommelse (se f.eks. ISO C++ Standarden §20.4.2).
Derfor at bestemt ikke noget sludder, at sige at:
* en constructor omformer raw storage til et gyldigt object
* en destructor omformer et gyldigt objekt til raw storage
Det er uden betydning, hvor objektet befinder sig.

> >> locals er ikke karakteristiske for C++ fordi dét der karakteriserer
> >> C++ i forhold til C er objekter. locals findes både i C og C++, derfor
> >> er de ikke karakteristiske for C++!
> >
> >Du har en mærkværdig opfattelse af C++.
> >Indrøm bare at du ikke kan lide det og at du ikke kender det.
>
> Hvis du betegner de tre linier jeg har skrevet ovenfor som
> "mærkværdige" vil jeg gerne høre hvorfor du har valgt at
> bruge C++. Da jeg startede med at anvende C++ i 1986 var
> det fordi det var det bedste kommercielle objektorienterede
> sprog (i 80'erne), og grunden til at jeg ikke anvender det længere
> er at denne forudsætning ikke længere holder.
>

Sidst i 80'erne syntes jeg at C++ så spændende ud, og ville gerne lære noget
om alt det objekt orienterede der blev snakket om. Jeg havde i forvejen lidt
C baggrund.
Jeg valgte ikke C++ for at kunne skrive "new" i stedet for "malloc"
Jeg er ikke stoppet ved en opfattelse af at C++ kun er velegnet til
objekt-orienteret programmering. Det er simpelt hen for kedeligt og
indskrænket. Der sker mange spændende ting med C++ f.eks. inden for template
meta programmering, som ikke er specielt objekt-orienteret.
C++ er for mig mest spændende, når flere paradigmer arbejder _effektivt_
sammen, f.eks. objekt-orienteret programmering og generisk programmering.

> >> Nu må du rette mig hvis jeg tager fejl, men jeg
> >> mener at huske, at en af de store grimmerter ved C++ er at exceptions
> >> ikke rydder op efter sig, og dermed laver memory leaks.
> >
> >Ok. Jeg retter dig. Det er absolut forkert.
>
> Gælder det også hvis jeg i starten af en try-blok allokerede et
> objekt på heapen som jeg vil deallokerer i slutningen af blokken,
> men der kastes en exception inden da, og jeg kun har fat i objektet
> med en pointer som er erklæret i try-blokken.
>

Læs appendix E i Bjarne Stroustrup's "The C++ Programming Language, Special
Edition" som du har i forvejen.
Læs eventuelt også
Exception C++
Herb Sutter
ISBN 0-201-61562-2

Det korte svar:
Nej, du har ret objektet bliver ikke frigivet hvis man kun har en almindelig
pointer til objektet (sproget _forhindrer_ ikke at man opfører sig
tåbeligt).

Det lidt længere svar:
Hvis du har et objekt som du vil deallokere i slutningen af blokken, så skal
den da ikke allokeres på heapen med mindre der er en ualmindelig god grund
til det.
At allokere objektet på heapen giver et performance overhead og åbner for
fejl som du beskriver.
Den skal allokeres som automatic variable (på stakken), så den frigives
automatisk uden problemer, uanset hvordan blokken forlades (med return fra
flere steder
eller exceptions).

Konkret:
<pseudo C++ code>

void foo1(void)
{
// might throw - no leak
some_class* some_object1 = new some_class(some_args1);
// might throw - "some_object1" will leak
some_class* some_object2 = new some_class(some_args2);

// might throw - "some_object1" and "some_object2" will leak
if(!some_object1->valid() || !some_object2->valid()) {
// oops - forgot to delete
// "some_object1" and "some_object2" will leak
return;
}

// might throw - "some_object1" and "some_object2" will leak
do_something_might_throw(some_object1, some_object2);

// for any reasonable C++ class, destructor does not throw
delete some_object1;
delete some_object2;
}

void foo2(void)
{
some_class* some_object1 = 0;
some_class* some_object2 = 0;

try {
// might throw
some_class* some_object1 = new some_class(some_args1);
// might throw
some_class* some_object2 = new some_class(some_args2);

// might throw - "some_object1" and "some_object2" will leak
if(!some_object1->valid() || !some_object2->valid()) {
// oops - forgot to delete
// "some_object1" and "some_object2" will leak

return;
}

// might throw
do_something_might_throw(some_object1, some_object2);

// for any reasonable C++ class, destructor does not throw
delete some_object1;
delete some_object2;
}
catch(...) {
// for any reasonable C++ class, destructor does not throw
delete some_object1;
delete some_object2;
throw; // rethrow
}
}

void foo3(void)
{
// might throw - no leak
std::auto_ptr<some_class> some_object1(new some_class(some_args1));
// might throw - no leak
std::auto_ptr<some_class> some_object2(new some_class(some_args2));

// might throw - no leak
if(!some_object1->valid() || !some_object2->valid()) {
return; // no leak
}

// might throw - no leak
do_something_might_throw(some_object1, some_object2);

// look mom - no leak
}

void foo4(void)
{
some_class some_object1(some_args1)); // might throw - no leak
some_class some_object2(some_args2)); // might throw - no leak

// might throw - no leak
if(!some_object1.valid() || !some_object2.valid()) {
return; // no leak
}

// might throw - no leak
do_something_might_throw(&some_object1, &some_object2);
}

<pseudo C++ code/>

Det er klart at "foo1" er unødig besværlig og fejlbehæftet. Kan ikke simpelt
reddes.

"foo2" prøver på at rette på problemerne med try/catch, men bliver langt
mere kompliceret
og er alligevel ikke korrekt. Den kan rettes, men er svær at vedligeholde.

"foo3" får fat om problemerne på det rigtige sted, men er stadig unødig
kompliceret og ineffektiv med den overflødig allokering på heapen, men
korrekt.

"foo4" er den simpleste, mest effektive og samtidig korrekt - hvor svært kan
det være ?

Husk det var dig der sagde at objektet skulle deallokeres i slutningen af
blokken.
Og i relation til resource styring og destructorer _er_ det ligegyldigt om
"foox" er member-funktioner eller ej!
Teknikken skalerer så afgjort til store applikationer.

Hvis objektet _ikke_ skal frigives i slutningen af blokken, er der grund til
at allokere objektet på heapen.
I så fald bør man anvende en "std::auto_ptr" fra C++ Standard Library indtil
alle de objekter man allokerer i forbindelse med en samlet handling, og når
alle delhandlinger er udført vil man overdrage ejerskabet til den rette
ejer.

Lad mig være helt konkret (jeg ikke har compileret, så der kan være
småfejl):

<C++ code>
// some date class, not exception safe for illustration purpose
class date;

class person
{
public:
person(const std::string& name_arg,
const std::string& address_arg,
const date& born_date_arg);
// copy constructor
person(const person& src);
// copy assignment operator
person& operator=(const person& rhs);
// destructor not required
// generated default destructor is fine

// attribute access functions goes here
const std::string name(void) const;
// ...

private:
std::string name_;
std::string address_;
// date class not fully exception safe
std::auto_ptr<date> born_date_;
};

person::person(const std::string& name_arg, const std::string& address_arg,
const date& born_date_arg) :
name_(name_arg), // might throw - no leak
address_(address_arg), // might throw - no leak
born_date_(new date(born_date_arg) // might throw - no leak
{
}

person::person(const person& src) :
// might throw - no leak
name_(src.name_),
// might throw - no leak
address_(src.address_),
// might throw - no leak
born_date(new date(src.born_date_arg))
{
}

person& person:erator=(const person& rhs)
{
// all object (propably) allocate on the heap,
// and lives longer than this function,
// if no error occur

// might throw - no leak
std::string temp_name(rhs.name_);
// might throw - no leak
std::string temp_address(rhs.address_);
// might throw - no leak
std::auto_ptr<date> temp_born_date(new date(rhs.born_date_));

// from now on nothing can go wrong.
// objekt state can be changed from one consistent state
// to another consistent state

name_.swap(temp_name); // does not throw
address_.swap(temp_address); // does not throw
born_date = temp_born_date; // does not throw

// look mom - no resource leak and no exception issue
return this;
}

int main(void)
{
// look mom - no resource leak
// no exception issue
std::vector<person> persons;

// might throw exceptions
read_all_persons_from_database(persons);

// might throw exceptions
add_persons_using_gui(persons);

// might throw exceptions
do_a_lot(persons);
}
<C++ code/>

Det er primært assignment operatoren og main, der er interssant.
Idet der hele tiden er et klart ejerskab, er der absolut ingen problemer med
leaks under nogen omstændigheder, og det er simpelt at programmere på den
måde!
Hvis assignment operatoren ikke _garanteret_ skulle være bringe objektet fra
een konstent tilstand til en anden konsistent tilstand (transactional
semantic), kunne den blot være

<C++ code>
person& person:erator=(const person& rhs)
{
// might throw - no leak
name_ = rhs.name_;
// might throw - no leak
address = rhs.address_;
// might throw - no leak
born_date = std::auto_ptr<date>(new date(rhs.born_date_));

// look mom - no resource leak and not exception issue
return this;
}
<C++ code/>

Tekniken skalerer så afgjort til store C++ applikationer.
Hvis man ikke havde "std::string" og "std::auto_ptr", og alt stadig skulle
være dynamisk (ikke noget med "char name[NAME_LENGTH];") ville det være
kompliceret og nemt at lave fejl.

> >Du kender tydeligvis ikke C++ særligt godt, hvilket er helt i orden, hvis
> >blot du ikke udtaler dig om det.
>
> Hvad skal jeg sige til det?
>

Ikke noget - blot lære

> >Ikke member funktion funktioner har sin beretigelse.
>
> I et funktionelt programmeringssprog, men det er C++ ikke, derfor
> er mit svar: Nej!
>

Du tager åbenlyst og dokumenterbart fejl.
Det kan jo ikke nytte noget at du forsøger at give indtryk af du ved bedre
end Bjarne Stroustrup hvad C++ er:
http://www.research.att.com/~bs/bs_faq.html#Object-Oriented-language
http://www.research.att.com/~bs/oopsla.pdf

Det er ok at du opfatter C++ på en stereotyp måde, men det er _ikke_ et C++
problem, det er _dit_ problem.
Det er muligvis også et oplysnings- og undvisnings-problem. Det forsøger jeg
at hjælpe på med mine kommentarer i denne tråd

> >Vi bliver nok overhovedet ikke enige, så det er nok ikke umagen værd.
>
> Nej, sikkert ikke, men nu skriver jeg primært også i denne tråd af
> hensyn til de andre der formodentlig også læser den - jeg har
> for længst opgivet at "frelse" dig
>

Netop
Jeg er uden for pædagogisk rækkevidde på dette område, men du kan stadig nå
at blive "frelst"

> Mit gennerelle indtryk er, at du ser verden fra C++ og ud, mens jeg
> _prøver_ at se udefra og ind i C++.
>
> >Byg du bare dine egne fordomme op, som forhindrer dig i at lære nye ting.
>
> Jeg lærer noget nyt hele tiden. F.eks. har jeg fået en _bedre_
> forståelse af at undgå memory leaks igennem denne tråd, men på
> trods af det synes jeg stadig at jeg skal binde den ene "C++-arm" på
> ryggen for at bruge "locals-lappen". Det bliver ikke kun et
> sprøgrsmål om en sund programmerinsgstil, men et spørgsmål om at
> jeg skal betragte visse dele af sproget som deprecated; hvilket bliver
> C--.
>

Prøv at se på mit "person" eksempel.
Det er simpelt, sikkert, effektivt og programmet er ikke på nogen måde
dynamisk begrænset.
Det er ikke noget med at man ikke _må_ bruge new og delete. Det er blot ikke
nødvendigt så ofte som mange har tendens til.

Det er ikke væsentligt anderledes, end at jeg (næsten) til enhver tid vil
anbefale at man bruger klassen "std::string" til streng behandling i C++ i
stedet for at arbejde med "char*" og "strcpy" - det er simplere og sikrere,
og næsten altid tilstrækkeligt effektivt.

> >Det er ikke memory - det er resource generelt.
>
> (I en face to face diskussion kan man beskrive tingene mere udførligt,
> i en post gør man det lidt kortere) Det gælder naturligvis også
> resourcer generelt, hvilket er grunden til at Java ikke bare klarer
> frisag med en garbage collector og det forkvaklede finalize (så nemt
> er det trods alt ikke at løse disse problemer).
>

Den er jeg klart med på.

> >Det er ikke automatic variable specifikt. Det er at have et vedstyret
> >ejerskab generelt, hvadenten det er som automatic variable eller som data
> >medlemmer i en klasse.
>
> I ethvert realistisk objektsystem findes der objekter der ikke er
> aggregeret andre objekter (ejet af), og en løsning der kræver at
> alle objekter er aggregeret, er for vidtgående i forhold til den
> indflydelse et sprog skal have på objektmodellen (nemlig ingen!)
>

Man kan ikke lave et design (objekt model) som er sprog uafhængigt !!!
Man skyder sig selv i foden, hvis man prøver.

> >> Jeg regner ikke nødvendigvis STL for at være "rigtig" C++. Hvis det
> >> ikke er objektorinteret kan det være lige så meget standard som det
> >> vil, det vil alligevel være usundt.
> >>
> >Ok. Så slap du katten ud af sækken.
> >Du er af den opfattelse at det objektorienterede paradigme er det eneste
> >sunde. Det er et fattigt verdenssyn.
>
> Jeg mener ikke at det objektorienterde paradigme er det eneste sunde
> paradigme, men det er det eneste sunde paradigme man med rimelig kan
> anvende C++ til.

Du har en fattig forståelse af C++, som ligger langt fra hvad Bjarne
Stroustrup havde i tankerne (http://www.research.att.com/~bs/oopsla.pdf).

Må jeg anbefale bogen
Multi-Paradigm DESIGN for C++
James O. Coplien
ISBN 0-201-82467-1
Det er en forholdvis krævende bog, og ikke alle har kapacitet til at forstå
den på nuværende tidspunkt.
Hvis du ikke kender Coplien, så er han
* den første uden for Bjarne Stroustrup's gruppe der brugte C++ (cfront)
* en af de første der skrev om patterns, inden ordet blev opfundet
* en af de meget væsentlige personer inden for hele pattern bevægelsen
* ham der stod den 11. september 2001 (om morgenen, inden dagen blev
historisk) på Java konferencen JAOO 2001 i Århus og forklarede hvorfor
objekt paradigmet ikke fungerer.
Det er ikke ualmindeligt at der går 5-10 år inden det han siger bliver
alment forstået.

> Til andre sunde paradigmer (funktionelle, logiske
> etc. findes langt mere målrettede sprog, multiparadigmiske sprog
> er en misforståelse af hvilket forhold der skal være mellem et
> sprog og et paradigme)
>

Det at kunne kombinere flere paradigmer effektivt i samme program er
overordentligt nyttigt, og nok en af de ting der tiltaler mig allermest ved
C++ (udover effektiviteten og den præcise udtrykskraft).

> >Du ved simpelt hen ikke hvad moderne C++ er. Fair nok, men så lad være
med
> >at udtale dig om det.
>
> "Moderne C++" - Hvad er det for en betegnelse? C++ er C++.

Det er igen en _meget_ unuanceret og stereotyp opfattelse.

> Hvad er umoderne C++? Er der dele af sproget som det er umoderne
> at bruge eller er "moderne C++" bare en betegnelse for den seneste
> programmeringsstil man skal tillægge sig hvis man skal undgå
> problemer. Hvorfor skal programmørerne løse sprogets problemer?
>

For en god beskrivelse af hvad "Moderne C++" er, se:
http://www.two-sdg.demon.co.uk/curbralan/papers/TheMiseducationOfC++.pdf
hvor de vil finde det beskrevet i forhold til "Early C++" og "Classic C++".
Se også
http://www.research.att.com/~bs/new_learning.pdf
for en introduktion til hvad "Moderne C++" er.
Eller bogen
Accelerated C++
Andrew Koenig, Barbara Moo
ISBN 0-201-70353-X
for en mere omfattende introduktion til "Moderne C++"

Baggrunden for udviklingen i brugen af C++ er naturligvis at man løbende
får en bedre forståelse af hvad det er for problemer man forsøger at løse,
og en bedre forståelse af hvordan man effektivt løser disse problemer.
Der er ikke noget overraskende i en sådan udvikling, og der er ikke nogen
grund til at den udvikling ikke vil fortsætte.
Det er ikke et C++ fænomen.

Man kan spørge, hvad kommer så efter "Modern C++" ?
Det kan man få et indtryk af ved at læse
Modern C++ Design
Andrei Alexandrescu
ISBN 0-201-70431-5
og www.boost.org og følge med med i hvad der sker omkring arbejdet med næste
version C++.

> Mig bekendt arbejder man ikke med betegnelsen "deprecated" i
> forbindelse med hverken C++ eller andre sprog (bemærk at jeg taler om
> _sproget_), så ville det være dets egen nekrolog.

Se Annex D i C++ Standarden (ISO/IEC 14882).
Se "deprecated-list.html" i Java V1.3, hvor der er listet hvad der er
"deprecated".
Man kan sige at det ikke er en del af _sproget_, altså lave en adskillelse
mellem "core language" og "library" - men det hænger uløseligt sammen.

> Hvis man har høstet
> erfaringer i retning af at der er sproglige konstruktioner i et sprog
> der er usunde at bruge, så lav et nyt sprog - ikke en ny
> programmeringsstil i sproget!
>

Det er naivt, unødvendigt og økonomisk uansvarligt.
Byg videre på det der virker, lav løsninger på det der erfaringsmæssigt
giver problemer.
Der står naturligvis ikke i forbindelse med C++, at det er "deprecated" at
lave resource leak - det har _aldrig_ være anbefalet praksis .

> >Ansvaret for initialisering og nedlæggelse af hele mit objektsystem
styres
> >fra main.
> >Tænk over det lidt. Det følger eksakt programmets behov.
>
> Jeg tror du kommer til at give mig et hint mere. Det eneste behov vi
> har for main er at få skubbet programmet forbi det punkt hvor der
> endnu ikke findes objekter.
>

Se igen mit "person" eksempel.

> >Ethvert sprog har sin stil og idioms, som man skal kende og udnytte hvis
man
> >skal bruge det effektivt.
>
> Det er rigtigt, men idiomer skal ikke løse problemer der burde være
> løst den dag sproget blev designet (Det er kun hypotetisk at de burde
> være løst da sproget blev designet, man kan naturligvis ikke forudse
> alle problemer der vil komme, efterhånden som sproget modnes. Det
> er også derfor man med ca. 10 års mellemrum bør smide et sprog væk
> og lave et nyt)
>

Igen det er naivt, unødvendigt og økonomisk uansvarligt.
Der er gode økonomiske og tekniske grunde til at der forsat kører meget
vigtig kode som COBOL, FORTRAN og PL/1 på mainframes den dag i dag.

> >Prøv helt objektivt at forklare mig, og andre læsere af denne tråd, hvad
der
> >er kompliceret i relation til resource styring ved at skrive:
> >
> >void foo(void)
> >{
> > string text("hello world");
> > cout < text;
> >}
>
> Meget simpelt eksempel, der skalerer dårligt. Jeg kan ikke se dette
> eksempel har fortsat relevans. Det er to linier kode, hvor du laver en
> local der naturligvis ikke giver problemer. Din pointe synes hele
> tiden at være: "Se, jeg laver en local, der er ikke noget problem",
> min pointe er "Se du laver _kun_ en local, skal vi prøve at lave lidt
> mere C++ end det?".
>

Nej, min pointe er hele tiden:
* undgå i så stor udstrækning som muligt at åbne _muligheden_ for leaks
* når der bruges "new", så gør hele tiden hele for hvem der har ansvaret
for nedlæggelsen, hvad enten det er eksekvering-konteksten (automatic
variable) eller det er som datamedlem i et objekt, hvor der er styr på
ejerskabet.

Fortæl hvad det er i mit "person" eksempel, der ikke skalerer ?
Det er fuldt dynamisk og allokerer på heapen, men giver _ingen_ _mulighed_
for fejl af den grund.

> Problemet er ikke hvordan det fungerer med et par linier kode og
> et par objekter. Jeg har vanskeligere ved at se det som en simpel
> løsning hvis vi taler om objektsystemer med _mange_ objekter.
> Problemet er ikke at løsningen ikke virker, men at den skaffer os af
> med et problemer og giver os et nyt, nemlig at skulle begrænse os til
> til locals og til disse's aggregering objekter.
>
> Hvis moderne C++ er "C++ hvor vi gør alt hvad vi kan for kun at bruge
> locals og aggregerede objekter (objekter der ejes af nogen)", så er
> moderne C++ kun et spørgsmål om at lave C++ der kan fungere "på
> trods af at det er skrevet i C++".
>

Hvad er alternativet til locals og aggregerede objekter i C++ ?
Er det en begrænsning ?


Venlig hilsen

Mogens Hansen







Flemming Jensen (30-03-2002)
Kommentar
Fra : Flemming Jensen


Dato : 30-03-02 19:53

On Sat, 30 Mar 2002 13:22:58 +0100, "Mogens Hansen"
<mogens_h@dk-online.dk> wrote:

>Udemærket, men det er ikke tilstrækkeligt at købe dem.

Uha, den var billig

>Det væsentlige er at man læser og forstår dem.
>Den væsentlige forskel mellem "Third Edition" (fra før foråret 2000) og
>"Special Edition" er appendix D (Locales) og appendix E (Standard Library
>Exception Safety).

For mig ligner denne udvikling trods alt en stadig strøm af
indsnævringer af hvad der er holdbar programmeringsstil.

>Du kan umuligt have læst og forstået appendix E, når du tidligere i denne
>tråd skrev:
><citat>
>Nu må du rette mig hvis jeg tager fejl, men jeg mener at huske, at en af de
>store grimmerter ved C++ er at exceptions ikke rydder op efter sig, og
>dermed laver memory leaks.
><citat/>

Du giver mig senere ret i at exceptions har problemer med memory
leaks - men det skyldes naturligvis et jeg ikke programmerer på
"den rigtige måde" - der i parantes bemærket, ene og alene er
dikteret af problemet med memory leaks.

Jeg skal forøvrigt bemærke at appendix D starter med at definere
en locale. Det er ikke den definition jeg har brugt i mine posts
når jeg har talt om locals - en local er en lokal variabel, der er
allokeret i activation framen. Det er den almindelige anvendelse af
ordet i forbindelse med compiler-programmering, hvilket var min
baggrund for at anvende det (det betyder givet vis at vi har talt
forbi hinanden i nogen sammenhænge!)

>Det er derfor der er brug for oplysning og undervisning, sådan som jeg har
>forsøgt i denne tråd. Det kræver naturligvis at budskabet bliver forklaret
>tilstrækkeligt godt, og modtagerne er villige og i stand til at lytte og
>forstå.

Jeg vil også gerne takke dig fordi du specielt i denne post har gjort
meget ud af at forklare tingene, det synes jeg du gør udemærket.

>Det vigtigste er: "den nemmeste måde at undgå leak i C++ er at lade være med
>at lave dem".

Jo, det har det jo altid været

>Det er derfor C++ Standard Library klasser som "std::string", "std::vector"
>og "std::auto_ptr" er vigtige.

Det er rigtigt, men der vil jeg så igen være hård og blot konstatere
at vi har fået tre lapper, de har endog fået deres egne navne.

>Det er derfor værktøjer (som f.eks. NuMega BoundsChecker, Rational Purify og
>Borland CodeGuard), som under udviklinger checker for klassiske C og C++
>fejl (som resource leaks, access to freed memroy, buffer overrun etc.) er
>vigtige.

Værktøjer til at disciplinere én til at programmere på den smalle vej,
løser måske memory leak problemet, men er problemet _ikke_ netop at
det burde spille så stor en rolle.

>Der er flere myter om problemer med leaks i C++ end der er reele problemer.

Det har du helt ret i. Tingene er ikke sort/hvide (det bliver de
let i postings hvor man er tilbøjelig til at fatte sig i korthed)

>Raw memory (eller mere korrekt raw storage) betyder i relation til C++
>uinitialiseret hukommelse (se f.eks. ISO C++ Standarden §20.4.2).
>Derfor at bestemt ikke noget sludder, at sige at:
> * en constructor omformer raw storage til et gyldigt object
> * en destructor omformer et gyldigt objekt til raw storage
>Det er uden betydning, hvor objektet befinder sig.

Jeg skal indrømme at jeg sjældent læse ISO standarder, men bare vi
kan blive enige om hvordan det er, så er det okay.

>Sidst i 80'erne syntes jeg at C++ så spændende ud, og ville gerne lære noget
>om alt det objekt orienterede der blev snakket om. Jeg havde i forvejen lidt
>C baggrund.
>Jeg valgte ikke C++ for at kunne skrive "new" i stedet for "malloc"
>Jeg er ikke stoppet ved en opfattelse af at C++ kun er velegnet til
>objekt-orienteret programmering. Det er simpelt hen for kedeligt og
>indskrænket. Der sker mange spændende ting med C++ f.eks. inden for template
>meta programmering, som ikke er specielt objekt-orienteret.

Man vælger først sit paradigme, så vælger man sit sprog (en lære-
sætning jeg naturligvis aldrig selv efterlever

Template klasser er bestemt OO. Hvis du med meta programmering mener
at man i sproget kan bruge makroer ol. til mere eller mindre at lave
sit eget sprog så tror jeg vi ser forskelligt på tingene
Det er noget man morer sig med, men bruge det til noget for alvor,
der er dybt usundt!

>C++ er for mig mest spændende, når flere paradigmer arbejder _effektivt_
>sammen, f.eks. objekt-orienteret programmering og generisk programmering.

Generisk programmering er ikke et paradigme, det er idé man finder
i mange sprog - bla. i alle OO-sprog jeg lige kan komme på.

>Det korte svar:
>Nej, du har ret objektet bliver ikke frigivet hvis man kun har en almindelig
>pointer til objektet (sproget _forhindrer_ ikke at man opfører sig
>tåbeligt).

At det er tåbeligt skyldes ene og alene at det kan give memory leaks.
Det er en af grundidéerne i mine argumenter, at det ikke er
acceptabelt at ens programmeringsstil skal dikteres af en teknikalitet
som memory leaks. Memory leaks er sprogets problem og det er sproget
der skal løse det.

>Det lidt længere svar:
>Hvis du har et objekt som du vil deallokere i slutningen af blokken, så skal
>den da ikke allokeres på heapen med mindre der er en ualmindelig god grund
>til det.

Du tager frihed fra programmøren ved at kræve at der skal være en god
grund, og Bjarne vil ikke have den slags, det ved du jo godt

"There is no one right way to write every program - and even if there
were there would be no way of forcing programmers to use it"
(http://www.research.att.com/~bs/bs_faq.html#Object-Oriented-language)

Problemet med de løsninger der findes i C++, på memory leak problemet,
er netop at de _totalt_ giver køb på denne sunde tanke, som jeg er
fuldstændig enig med Bjarne i (hvilket visse guruer bestemt ikke er!)

Hvis jeg skulle svare på alle de postings der har været i forbindelse
med denne tråd, skulle det være med Bjarnes to linier ovenfor - de
fejer totalt løsningen med locals af banen! Man kan ganske enkelt ikke
pålægge folk at programmere "Moderne" C++.

>Konkret:
><pseudo C++ code>
>
>void foo1(void)
>
>void foo2(void)
>
>void foo3(void)
>
>void foo4(void)
>
><pseudo C++ code/>

Der er ikke noget nyt for mig i disse eksempler, jeg ved godt hvad vi
snakker om. Spørgsmålet er ikke om det virker eller om det er smart
at gøre det på den ene måde eller den anden, for det er smart
og det virker! Spørgsmålet er: "Kan man pålægge min programmerings-
stil så snævre begrænsninger, og samtidig sige at der ikke er et
problem?"

>Teknikken skalerer så afgjort til store applikationer.

Nu er det mest spørgsmålet om det skalerer i store _objektsystemer_,
jeg stiller spørgsmål ved (heterogene objektsystemer, ellers er
det trivielt at det skalerer)

><C++ code>
>// some date class, not exception safe for illustration purpose
>class date;
>
>class person
> ...
><C++ code/>

Det begynder efterhånden at blive interessant, men lad os dreje
kompleksiteten lidt mere. Hvordan laver man en container klasse,
der bruger en linked list (hægtet liste), enkeltkædet, som
du selv implementerer (ikke noget med at finde det i STL).
Hvordan sletter man sikkert fra en sådan liste, uden at det
gør galt (idet vi antager at vi ikke bruger delete, for det
glemmer vi jo bare alligevel)

Hvordan vil du placerer ejerforholdet så det kan realiseres
med locals?

>Tekniken skalerer så afgjort til store C++ applikationer.

Når jeg spørger om den skalerer er det ikke en påstand om at
den ikke gør - jeg ved det ikke - jeg har bare min tvivl.

>Hvis man ikke havde "std::string" og "std::auto_ptr", og alt stadig skulle
>være dynamisk (ikke noget med "char name[NAME_LENGTH];") ville det være
>kompliceret og nemt at lave fejl.

Jo, men hvis vi ikke gør det, er det jo heller ikke "rigtig" C++,
eller hvordan er det nu lige

>Ikke noget - blot lære

Det er bestemt også mere interessant at lære, end at få ret.

>> >Ikke member funktion funktioner har sin beretigelse.
>>
>> I et funktionelt programmeringssprog, men det er C++ ikke, derfor
>> er mit svar: Nej!
>>
>
>Du tager åbenlyst og dokumenterbart fejl.
>Det kan jo ikke nytte noget at du forsøger at give indtryk af du ved bedre
>end Bjarne Stroustrup hvad C++ er:
> http://www.research.att.com/~bs/bs_faq.html#Object-Oriented-language
> http://www.research.att.com/~bs/oopsla.pdf

Det gør jeg nok ikke, men hvis du ville høre den objektive sandhed
om Java, ville du så spørge Gosling? Jeg ville ikke, og specielt
det Bjarne skriver i de to første linier af:
(http://www.research.att.com/~bs/bs_faq.html#Object-Oriented-language)
er meget subjektivt, for han bryder det selv efter behag, f.eks. i
forbindelse med løsningen af memory leaks

Bjarne ved selvfølge meget mere om C++ end jeg gør, og det gør du
også, men jeg tvivler på at nogen af jer er specielt objektive, det er
jeg sikkert heller ikke.

Bjarne vil gerne sælge C++ som et multi-paradigmisk programmerings-
sprog, det kan han bare ikke. Det er et concept der stammer tilbage
fra gamle dage i universitets-verden hvor man gerne ville afprøve
nye paradigmer, men ikke havde tid/råd til at lave et nyt sprog hver
gang man ville afprøve noget, og derfor brugte man sprog på de mest
mærkværdige måder. Bjarne skriver selv at det kan være frustrende
at skrive i Smalltalk-stil i C++, og hvorfor skulle man da også det.
Hvis man gerne vil skrive i Smalltalk-stil så skrive da i Smalltalk.

Generelt er det naturligvis interessant hvad Bjarne skriver om
C++, specielt når der er tale om svar på kritik, men tage udgangs-
punkt i hvad man skal mene om et sprog ved at læse artikler og
bøger skrevet af sprogets skaber er ikke holdbart, så er alle
sprog nemlig rigtig, rigtig gode - selv COBOL

>> >Det er ikke automatic variable specifikt. Det er at have et vedstyret
>> >ejerskab generelt, hvadenten det er som automatic variable eller som data
>> >medlemmer i en klasse.
>>
>> I ethvert realistisk objektsystem findes der objekter der ikke er
>> aggregeret andre objekter (ejet af), og en løsning der kræver at
>> alle objekter er aggregeret, er for vidtgående i forhold til den
>> indflydelse et sprog skal have på objektmodellen (nemlig ingen!)
>>
>
>Man kan ikke lave et design (objekt model) som er sprog uafhængigt !!!
>Man skyder sig selv i foden, hvis man prøver.

Det gør man sikkert i C++, men det er bestemt også et af problemerne
med sproget, for det er helt uholdbart at designet skal laves med
hensyntagen til sproget.

Ultimativt burde sproget slet ikke være valgt når man laver designet,
men det er trods alt utopi

>> >> Jeg regner ikke nødvendigvis STL for at være "rigtig" C++. Hvis det
>> >> ikke er objektorinteret kan det være lige så meget standard som det
>> >> vil, det vil alligevel være usundt.
>> >>
>> >Ok. Så slap du katten ud af sækken.
>> >Du er af den opfattelse at det objektorienterede paradigme er det eneste
>> >sunde. Det er et fattigt verdenssyn.
>>
>> Jeg mener ikke at det objektorienterde paradigme er det eneste sunde
>> paradigme, men det er det eneste sunde paradigme man med rimelig kan
>> anvende C++ til.
>
>Du har en fattig forståelse af C++, som ligger langt fra hvad Bjarne
>Stroustrup havde i tankerne (http://www.research.att.com/~bs/oopsla.pdf).

Bjarne har i tankerne at C++ er multiparadigmisk, så uanset hvad der
sker så er C++ det bedste - det holder bare ikke en meter!

>Må jeg anbefale bogen
> Multi-Paradigm DESIGN for C++
> James O. Coplien
> ISBN 0-201-82467-1
>Det er en forholdvis krævende bog, og ikke alle har kapacitet til at forstå
>den på nuværende tidspunkt.
>Hvis du ikke kender Coplien, så er han
> * den første uden for Bjarne Stroustrup's gruppe der brugte C++ (cfront)
> * en af de første der skrev om patterns, inden ordet blev opfundet
> * en af de meget væsentlige personer inden for hele pattern bevægelsen
> * ham der stod den 11. september 2001 (om morgenen, inden dagen blev
>historisk) på Java konferencen JAOO 2001 i Århus og forklarede hvorfor
>objekt paradigmet ikke fungerer.
>Det er ikke ualmindeligt at der går 5-10 år inden det han siger bliver
>alment forstået.

Jeg har ingen guruer - jeg er ligeglad med folks CV, jeg er kun
interesseret i deres argumenter.

>Det at kunne kombinere flere paradigmer effektivt i samme program er
>overordentligt nyttigt,

og utrolig farligt,

> og nok en af de ting der tiltaler mig allermest ved
>C++ (udover effektiviteten og den præcise udtrykskraft).

Du er blevet forført. At programmere med flere paradigmer i det samme
sprog kræver en disciplin der er uhyggelig meget større end den
disciplin der skal til for at undgå memory leaks på den hårde måde.
Teoretisk er mulitparadigmiske sprog en smuk idé, det holder bare ikke
når man sætter mennesker af kød og blod til at administrere det, så
ender det i et paradigmisk kaos. Man plukker hist og her efter hvad
man har lydt til. Fordelen ved at programmere i et paradigmisk
målrettet sprog, er at alt hvad man laver bliver udtryk i det
univers som pardigmet udspænder, og dermed er det begrebsmæssige
grundlag solidt og entydigt helt fra grunden af (at man så kan
bygge noget rod ovenpå er en anden sag, der er ikke det sprog en
dårlig programmør ikke kan ødelægges)

>> "Moderne C++" - Hvad er det for en betegnelse? C++ er C++.
>
>Det er igen en _meget_ unuanceret og stereotyp opfattelse.

Når man virkelig skal prøve tingene af, er man nød til at
belaste dem hårdt, og dermed også være hård i sin kritik.
Løsningen med locals fungerer, og der er mange der bruger den,
og den løser sikkert også mange problemer. Men ... er det
virkelig det bedste vi kan lave? I C++ er svaret nok: Ja, men
så er valget måske ikke: C++ (det afhænger naturligvis også
af mange andre ting - memory leaks er naturligvis ikke hele
historien)

Jeg ved ikke om du kender Ian Joyner's "A Critique of C++",
hvor han sabler C++ ned fra alle sider. Den er meget interessant
at læse, men bliver lidt kedelig i længden fordi den netop
kun synes at drejer sig om at sable C++, bare for at gøre det.
Der er dog nogle dele af hans kritik jeg er enig i, men så
slem som ham er jeg nu langt fra

>Se Annex D i C++ Standarden (ISO/IEC 14882).
>Se "deprecated-list.html" i Java V1.3, hvor der er listet hvad der er
>"deprecated".
>Man kan sige at det ikke er en del af _sproget_, altså lave en adskillelse
>mellem "core language" og "library" - men det hænger uløseligt sammen.

Det er korrekt, det er _ikke_ en del af sproget. Det er en helt
grundlæggende og sund design-idé, der ligger bag at adskille de to fra
hinanden, og et af problemerne med løsningen på memory leaks i C++ er
da også at man i så høj grad baserer det på, at et sprogligt problem
(memory leaks) skal løses af et library (STL). Man kan naturligvis
diskutere om memory leaks er et sprogligt problem, men det er mit
syn på det.

>> Hvis man har høstet
>> erfaringer i retning af at der er sproglige konstruktioner i et sprog
>> der er usunde at bruge, så lav et nyt sprog - ikke en ny
>> programmeringsstil i sproget!
>>
>
>Det er naivt, unødvendigt og økonomisk uansvarligt.

Det kan jeg dårligt sige noget til, det er vel et sprogsmål om
hvad man prioriterer.

>Byg videre på det der virker, lav løsninger på det der erfaringsmæssigt
>giver problemer.

Så er der så meget der virker, hvorfor ikke bygge ovenpå Algol? Eller
som jeg nogle gange spøger med: "Jeg vil stå fader til Objekt-
orienteret Assembler"

>Der står naturligvis ikke i forbindelse med C++, at det er "deprecated" at
>lave resource leak - det har _aldrig_ være anbefalet praksis .

Nej, men når folk kommer med simple små programmer, der i sig
selv er ganske harmløse (f.eks. exceptions med pointere involveret),
har de fået at vide at det var dem der var noget galt med, ikke
sproget; hvilket er noget sludder.

>> >Ansvaret for initialisering og nedlæggelse af hele mit objektsystem
>styres
>> >fra main.
>> >Tænk over det lidt. Det følger eksakt programmets behov.
>>
>> Jeg tror du kommer til at give mig et hint mere. Det eneste behov vi
>> har for main er at få skubbet programmet forbi det punkt hvor der
>> endnu ikke findes objekter.
>>
>
>Se igen mit "person" eksempel.

Din main i person-eksemplet eksporterer blot problemet til STL.
Idéen synes at være. Vi laver nogle generelle klasser i STL, og
tester dem til hudløshed for memory leaks, dernæst fortæller
vi folk at de er tåbelige hvis de laver den slags kode som
vi selv netop har gjort - det er ikke holdbart! Men lad os kalde
det umoderne så siger de os nok ikke imod!

>> >Ethvert sprog har sin stil og idioms, som man skal kende og udnytte hvis
>man
>> >skal bruge det effektivt.
>>
>> Det er rigtigt, men idiomer skal ikke løse problemer der burde være
>> løst den dag sproget blev designet (Det er kun hypotetisk at de burde
>> være løst da sproget blev designet, man kan naturligvis ikke forudse
>> alle problemer der vil komme, efterhånden som sproget modnes. Det
>> er også derfor man med ca. 10 års mellemrum bør smide et sprog væk
>> og lave et nyt)
>>
>
>Igen det er naivt, unødvendigt og økonomisk uansvarligt.
>Der er gode økonomiske og tekniske grunde til at der forsat kører meget
>vigtig kode som COBOL, FORTRAN og PL/1 på mainframes den dag i dag.

Okay, så siger vi jeg er naiv - men jeg synes bare verden kunne
være et så godt sted at være hvis vi gjorde det

>Nej, min pointe er hele tiden:
> * undgå i så stor udstrækning som muligt at åbne _muligheden_ for leaks
> * når der bruges "new", så gør hele tiden hele for hvem der har ansvaret
>for nedlæggelsen, hvad enten det er eksekvering-konteksten (automatic
>variable) eller det er som datamedlem i et objekt, hvor der er styr på
>ejerskabet.

Jo, men det er vel netop også det komplicerede, at vi skal slæbe
rundt på denne ekstra huskeliste. Når jeg taler om kompliseret, er
det ikke et sprøgsmål om at noget er _svært_, det er et spørgsmål om
at sammenligne med andre løsninger, f.eks. en garbage collector. En
garbage collector giver andre problemer, men hvilke problemer er
størst?

>Fortæl hvad det er i mit "person" eksempel, der ikke skalerer ?
>Det er fuldt dynamisk og allokerer på heapen, men giver _ingen_ _mulighed_
>for fejl af den grund.

Dit eksempel er meget homogent, idet det kun arbejder med én klasse
i noget så simpelt som en vector. At lave 100 eller 10.000 instanser
af den samme klasse og proppe dem i en container er ikke det jeg mener
med skalering. Jeg tænker på mere heterogene objektsystemer; hvor det
kan være et problem at placere ansvaret for at nedlægge et objekt;
hvor ejerskab ikke så let lader sig placere.

(Jeg har ikke på stående fod et eksempel - jeg vil dog gerne se
løsningen på sletning af et element i en linked list, som jeg
nævner ovenfor)

Mit grundlæggende problem, i forhold til løsningen, er at jeg ikke
vil have at sprøgsmålet om aggregering skal være et implementations-
spørgsmål, men aller senest et design-spørgsmål.

>Hvad er alternativet til locals og aggregerede objekter i C++ ?
>Er det en begrænsning ?

Det er en begrænsning, og der er nok ikke noget alternativ. Hvis der
var, er jeg sikker på Bjarne havde fundet det.


/Flemming Jensen


Mogens Hansen (31-03-2002)
Kommentar
Fra : Mogens Hansen


Dato : 31-03-02 00:11


"Flemming Jensen" <nospam@nospam.com> wrote
> On Sat, 30 Mar 2002 13:22:58 +0100, "Mogens Hansen"
> <mogens_h@dk-online.dk> wrote:

>
> >Det væsentlige er at man læser og forstår dem.
> >Den væsentlige forskel mellem "Third Edition" (fra før foråret 2000) og
> >"Special Edition" er appendix D (Locales) og appendix E (Standard Library
> >Exception Safety).
>
> For mig ligner denne udvikling trods alt en stadig strøm af
> indsnævringer af hvad der er holdbar programmeringsstil.
>

Sådan kan man se så forskelligt på tingene.
For mig er appendix E, og det øvrige arbejde der er lavet for at forstå og
bruge bruge exceptions, et kæmpe skridt fremad i relation til at gøre
fejlhåndteringen simplere og mere komplet.
Fejlhåndtering i programmer er ofte et ømt punkt.

> >Du kan umuligt have læst og forstået appendix E, når du tidligere i denne
> >tråd skrev:
> ><citat>
> >Nu må du rette mig hvis jeg tager fejl, men jeg mener at huske, at en af
de
> >store grimmerter ved C++ er at exceptions ikke rydder op efter sig, og
> >dermed laver memory leaks.
> ><citat/>
>
> Du giver mig senere ret i at exceptions har problemer med memory
> leaks - men det skyldes naturligvis et jeg ikke programmerer på
> "den rigtige måde" - der i parantes bemærket, ene og alene er
> dikteret af problemet med memory leaks.
>

Nej, det giver jeg dig bestemt _ikke_ ret i.
Memory leaken opstår ikke pga. af en exception - den opstår fordi man
forlader scope uden at have overdraget ejerskabet til noget.
Det er ligegyldigt om det er pga. en exception eller med et return.
Det er ikke mere rigtigt end at sige at det er "return", der er årsag til en
leak.
"return" og exceptions har _ikke_ problemer med resource leaks.

> Jeg skal forøvrigt bemærke at appendix D starter med at definere
> en locale. Det er ikke den definition jeg har brugt i mine posts
> når jeg har talt om locals - en local er en lokal variabel, der er
> allokeret i activation framen. Det er den almindelige anvendelse af
> ordet i forbindelse med compiler-programmering, hvilket var min
> baggrund for at anvende det (det betyder givet vis at vi har talt
> forbi hinanden i nogen sammenhænge!)
>

Nej, jeg har hele tiden været klar over at du har ment automatic variable.
Locale i forbindelse med appendix D er noget med forskellig geografisk
regional skik og brug.
Vi har ikke talt forbi hinanden - kan du finde et eksempel på det ?

>
> Jeg vil også gerne takke dig fordi du specielt i denne post har gjort
> meget ud af at forklare tingene, det synes jeg du gør udemærket.
>

Tak.

>
> >Det er derfor C++ Standard Library klasser som "std::string",
"std::vector"
> >og "std::auto_ptr" er vigtige.
>
> Det er rigtigt, men der vil jeg så igen være hård og blot konstatere
> at vi har fået tre lapper, de har endog fået deres egne navne.
>

Jeg opfatter det bestemt ikke som lapper.
Jeg opfatter det som effektive til virkelig programmering.

> >Der sker mange spændende ting med C++ f.eks. inden for template
> >meta programmering, som ikke er specielt objekt-orienteret.
>
>
> Template klasser er bestemt OO. Hvis du med meta programmering mener
> at man i sproget kan bruge makroer ol. til mere eller mindre at lave
> sit eget sprog så tror jeg vi ser forskelligt på tingene
> Det er noget man morer sig med, men bruge det til noget for alvor,
> der er dybt usundt!
>

Jeg mener "Template Metaprogramming", sådan som det f.eks. er beskrevet i
bogen
Generativ Programming
Krzysztof Czarnecki, Ulrich W. Eisenecker
ISBN 0-201-30977-7
i kapitel 10, og især omkring side 413.

Det har _ikke_ noget med makroer at gøre.
Det er f.eks. noget med
* at repræsentere meta information med forskellige former for traits.
* skrive metafunktioner for at beregne typer og tal
* bruge statiske control strukturer
* bruge metafunktioner til at generere kode
* udvikle domæne specifikke sprog ved hjælp af expression templates

Det er bestemt ikke usundt!
Prøv at se bogen - det er dybt spændende.

> >C++ er for mig mest spændende, når flere paradigmer arbejder _effektivt_
> >sammen, f.eks. objekt-orienteret programmering og generisk programmering.
>
> Generisk programmering er ikke et paradigme, det er idé man finder
> i mange sprog - bla. i alle OO-sprog jeg lige kan komme på.
>

Ved generisk programmering forstår jeg programmering med generiske
parametre, sådan som det f.eks. ses i STL.
Det er også noget med compile-time polymorphy.
Hvor finder du den form for generisk programmering i f.eks. Java og C# ?

> >Det korte svar:
> >Nej, du har ret objektet bliver ikke frigivet hvis man kun har en
almindelig
> >pointer til objektet (sproget _forhindrer_ ikke at man opfører sig
> >tåbeligt).
>
> At det er tåbeligt skyldes ene og alene at det kan give memory leaks.

Hvis målet er at bekræfte dig selv så fint.
Men giv mig een _god_ grund til at ville programmere sådan.
Det er mere kompliceret at programmere, det giver mulighed for fejl, der
giver dårligere run-time performance.

> Det er en af grundidéerne i mine argumenter, at det ikke er
> acceptabelt at ens programmeringsstil skal dikteres af en teknikalitet
> som memory leaks. Memory leaks er sprogets problem og det er sproget
> der skal løse det.
>

Jeg mener ikke at det er sprogets opgave at forhindre programmører i at lave
tåbelige ting, når det er nemmere at lave fornuftig kode.
Alle programmeringssprog kan bruges til at lave tåbelig og fejlbehæftet
kode.
Hvis det var nemmere at lave fejlbehæftet kode, var der måske noget at
brokke sig over.

Du er på ingen måde dikteret en ikke at allokere på heapen, selvom det er
tåbeligt, du skal blot leve op til det ansvar der følger med friheden.
Jeg viste 2 måder (foo2 og foo3) som begge allokerede på stakken og som
enten var korrekt eller kunne bringes til at være korrekte. Naturligvis er
det dit valg som programmør.

> >Det lidt længere svar:
> >Hvis du har et objekt som du vil deallokere i slutningen af blokken, så
skal
> >den da ikke allokeres på heapen med mindre der er en ualmindelig god
grund
> >til det.
>
> Du tager frihed fra programmøren ved at kræve at der skal være en god
> grund, og Bjarne vil ikke have den slags, det ved du jo godt
>

Vrøvl.

> "There is no one right way to write every program - and even if there
> were there would be no way of forcing programmers to use it"
> (http://www.research.att.com/~bs/bs_faq.html#Object-Oriented-language)
>
> Problemet med de løsninger der findes i C++, på memory leak problemet,
> er netop at de _totalt_ giver køb på denne sunde tanke, som jeg er
> fuldstændig enig med Bjarne i (hvilket visse guruer bestemt ikke er!)
>

Jeg syntes du tolker citatet ud over hvad der er belæg for.
C++ er i høj grad præget af frihed under ansvar.
Skriv dog endelig ligeså mange "new" som du overhovedet kan, når blot du
lever op til det ansvar der følger med.

> Hvis jeg skulle svare på alle de postings der har været i forbindelse
> med denne tråd, skulle det være med Bjarnes to linier ovenfor - de
> fejer totalt løsningen med locals af banen! Man kan ganske enkelt ikke
> pålægge folk at programmere "Moderne" C++.
>

Jeg har _ikke_ sagt at man _kun_ skal bruge automatic variables.
Jeg har har sagt at man i C++ kunne skal gøre rede for hvem der har ansvaret
for oprydning, hvad enten det er som datamedlemmer i andre objekter eller
som automatic variables.

> Spørgsmålet er: "Kan man pålægge min programmerings-
> stil så snævre begrænsninger, og samtidig sige at der ikke er et
> problem?"
>

Vær konkret.
Hvilke snævre begrænsninger snakker vi om ? (Og lad være med at gentage dig
selv, med at vi _kun_ må bruge automatic variables, for det har jeg _ikke_
sagt!)

> >Teknikken skalerer så afgjort til store applikationer.
>
> Nu er det mest spørgsmålet om det skalerer i store _objektsystemer_,
> jeg stiller spørgsmål ved (heterogene objektsystemer, ellers er
> det trivielt at det skalerer)
>

Mit arbejde er at lave _store_ _objektsystemer_, og det virker.

>
> Det begynder efterhånden at blive interessant, men lad os dreje
> kompleksiteten lidt mere. Hvordan laver man en container klasse,
> der bruger en linked list (hægtet liste), enkeltkædet, som
> du selv implementerer (ikke noget med at finde det i STL).
> Hvordan sletter man sikkert fra en sådan liste, uden at det
> gør galt (idet vi antager at vi ikke bruger delete, for det
> glemmer vi jo bare alligevel)
>

Hvorfor skulle man undlade at bruge new og delete til at implementere den
effektivt med ?
Naturligvis kan man selv implementere en korrekt hægtet liste.
Brugeren af klassen behøves ikke at skrive new og delete.
Dem der koder C++ Standard Library har ikke adgang til flere
sprogkonstruktioner end os andre.
Der er ikke noget i vejen med at det er mere kompliceret at implementere en
god, enkelt hægtet liste, end det er at bruge den.
Sådan bør det være at skrive biblioteker, for ellers var det ikke nogen
gevindst ved at bruge dem.

Jeg kan ikke se at der er noget galt i at man adskiller det at skrive
generelle klassebiblioteker (som f.eks. STL) fra det at bruge dem. Der er
ikke noget galt i at det er forskellige dele af sproget der vejer tungest
afhængigt af hvilken opgave man løser.

Skriv en god hægtet liste, som er nem at bruge og så _brug_ den flittig.
Hvor svært kan det være ?

> Hvordan vil du placerer ejerforholdet så det kan realiseres
> med locals?
>

Jeg har _ikke_ sagt at alt skal være automatic variables.
Jeg har sagt at man skal hele tiden kunne gøre rede for ejerskabet, hvad
enten det er som datamedlem i en anden klasse eller ved hjælp af
eksekveringskonteksten.
Der er ikke nogen grund til at forsøge at implementere en hægtet liste ved
hjælp af automatic variables.

> >Tekniken skalerer så afgjort til store C++ applikationer.
>
> Når jeg spørger om den skalerer er det ikke en påstand om at
> den ikke gør - jeg ved det ikke - jeg har bare min tvivl.
>

Det behøves du ikke at tvivle på.
Jeg har været med til at skrive store C++ applikationer professionelt de
sidste 12 år. Jeg _ved_ at det virker.

> >Hvis man ikke havde "std::string" og "std::auto_ptr", og alt stadig
skulle
> >være dynamisk (ikke noget med "char name[NAME_LENGTH];") ville det være
> >kompliceret og nemt at lave fejl.
>
> Jo, men hvis vi ikke gør det, er det jo heller ikke "rigtig" C++,
> eller hvordan er det nu lige
>

Lad være med at putte ord i munden på mig som jeg ikke har sagt!
Jeg har ikke udtalt mig om hvad der er "rigtig" C++.
Jeg har udtalt mig om hvad der er "moderne C++" ud fra den opfattelse der er
almindeligt gældende i C++ kredse.
Jeg har vist at man ikke behøves at gå på kompromis mellem korrekthed,
enkelhed i koden, deterministisk opførsel og dynamisk fleksibilitet.
Naturligvis er der et performance overhead ved at køre med dynamisk at
allokere strenge, hvis der ikke er _behov_ for det i problem domainet - men
det er en anden sag.

>
> Det gør jeg nok ikke, men hvis du ville høre den objektive sandhed
> om Java, ville du så spørge Gosling? Jeg ville ikke, og specielt
> det Bjarne skriver i de to første linier af:
> (http://www.research.att.com/~bs/bs_faq.html#Object-Oriented-language)
> er meget subjektivt, for han bryder det selv efter behag, f.eks. i
> forbindelse med løsningen af memory leaks
>

Vrøvl.

>
> Bjarne vil gerne sælge C++ som et multi-paradigmisk programmerings-
> sprog, det kan han bare ikke.

C++ _er_ et multi-paradigmisk sprog, og det er min _erfaring_ gennem mange
år at det fungerer glimrende som sådan.

>
> Generelt er det naturligvis interessant hvad Bjarne skriver om
> C++, specielt når der er tale om svar på kritik, men tage udgangs-
> punkt i hvad man skal mene om et sprog ved at læse artikler og
> bøger skrevet af sprogets skaber er ikke holdbart, så er alle
> sprog nemlig rigtig, rigtig gode - selv COBOL
>

Jeg tager udgangspunkt i min professionelle erfaring gennem mange år.
Jeg finder ingen uoverensstemmelse mellem min erfaring og hvad Bjarne
Stroustrup beskriver i sine bøger og papirer.

> Det gør man sikkert i C++, men det er bestemt også et af problemerne
> med sproget, for det er helt uholdbart at designet skal laves med
> hensyntagen til sproget.
>

Det er naivt at tro noget andet.

>
> Bjarne har i tankerne at C++ er multiparadigmisk, så uanset hvad der
> sker så er C++ det bedste - det holder bare ikke en meter!
>

Bevis at C++ ikke er eller ikke fungerer som multiparadigmisk
programmeringssprog !
Erfaring fra mange steder viser at det holder fint.

> >Må jeg anbefale bogen
> > Multi-Paradigm DESIGN for C++
> > James O. Coplien
> > ISBN 0-201-82467-1
> >Det er en forholdvis krævende bog, og ikke alle har kapacitet til at
forstå
> >den på nuværende tidspunkt.
> >Hvis du ikke kender Coplien, så er han
> > * den første uden for Bjarne Stroustrup's gruppe der brugte C++
(cfront)
> > * en af de første der skrev om patterns, inden ordet blev opfundet
> > * en af de meget væsentlige personer inden for hele pattern bevægelsen
> > * ham der stod den 11. september 2001 (om morgenen, inden dagen blev
> >historisk) på Java konferencen JAOO 2001 i Århus og forklarede hvorfor
> >objekt paradigmet ikke fungerer.
> >Det er ikke ualmindeligt at der går 5-10 år inden det han siger bliver
> >alment forstået.
>
> Jeg har ingen guruer - jeg er ligeglad med folks CV, jeg er kun
> interesseret i deres argumenter.
>

Tja, sådan kan man jo se på det.
Min erfaring er at folk der gennem en periode har sagt fornuftige ting,
bliver ved med det. Tiden er en hård dommer for ens udsagn. Hvis de siger
noget man ikke umiddelbart forstår, bør man måske tænke sig om en gang til.

> >Det at kunne kombinere flere paradigmer effektivt i samme program er
> >overordentligt nyttigt,
>
> og utrolig farligt,
>

De fleste ting er farlige i ukyndige hænder.

> > og nok en af de ting der tiltaler mig allermest ved
> >C++ (udover effektiviteten og den præcise udtrykskraft).
>
> Du er blevet forført.

Vrøvl.

> At programmere med flere paradigmer i det samme
> sprog kræver en disciplin der er uhyggelig meget større end den
> disciplin der skal til for at undgå memory leaks på den hårde måde.

Jeg er enig i at det er langt sværere at designe store systemer som bedst
klares med flere paradigmer kombineret end at undgå resource leaks. Men det
er mere fordi det er svært at designe store systemer og simpelt at undgå
resource leaks.

> Teoretisk er mulitparadigmiske sprog en smuk idé, det holder bare ikke
> når man sætter mennesker af kød og blod til at administrere det, så
> ender det i et paradigmisk kaos. Man plukker hist og her efter hvad
> man har lydt til.

Vrøvl.
Det kræver som al andet software udvikling: viden, erfaring, intelligens og
god smag.
Det er jo ikke noget noget med at klaske flest mulige paradigmer sammen på
kortest tid og plads.

> >> "Moderne C++" - Hvad er det for en betegnelse? C++ er C++.
> >
> >Det er igen en _meget_ unuanceret og stereotyp opfattelse.
>
> Når man virkelig skal prøve tingene af, er man nød til at
> belaste dem hårdt, og dermed også være hård i sin kritik.
> Løsningen med locals fungerer, og der er mange der bruger den,
> og den løser sikkert også mange problemer.

Nu må du simpelt hen holde op, men _kun_ at snakke om om locals (automatic
variables).
Det er simpelt hen ikke det jeg har sagt!

> Men ... er det
> virkelig det bedste vi kan lave? I C++ er svaret nok: Ja, men
> så er valget måske ikke: C++ (det afhænger naturligvis også
> af mange andre ting - memory leaks er naturligvis ikke hele
> historien)
>

Prøv at læs og _forstå_ hvad jeg har skrevet.

> Jeg ved ikke om du kender Ian Joyner's "A Critique of C++",
> hvor han sabler C++ ned fra alle sider. Den er meget interessant
> at læse, men bliver lidt kedelig i længden fordi den netop
> kun synes at drejer sig om at sable C++, bare for at gøre det.
> Der er dog nogle dele af hans kritik jeg er enig i, men så
> slem som ham er jeg nu langt fra
>

Nej, jeg kender den ikke - har det et link ?

> >
> >Se igen mit "person" eksempel.
>
> Din main i person-eksemplet eksporterer blot problemet til STL.
> Idéen synes at være. Vi laver nogle generelle klasser i STL, og
> tester dem til hudløshed for memory leaks, dernæst fortæller
> vi folk at de er tåbelige hvis de laver den slags kode som
> vi selv netop har gjort - det er ikke holdbart! Men lad os kalde
> det umoderne så siger de os nok ikke imod!
>

Vrøvl.
Men der er da en klar skelnen mellem hvad der kræves for at skrive
biblioteker og hvad der kræves for at skrive applikationer der bruger
bibliotekerne.

>
> >Nej, min pointe er hele tiden:
> > * undgå i så stor udstrækning som muligt at åbne _muligheden_ for leaks
> > * når der bruges "new", så gør hele tiden hele for hvem der har
ansvaret
> >for nedlæggelsen, hvad enten det er eksekvering-konteksten (automatic
> >variable) eller det er som datamedlem i et objekt, hvor der er styr på
> >ejerskabet.
>
> Jo, men det er vel netop også det komplicerede, at vi skal slæbe
> rundt på denne ekstra huskeliste.

Hvad i mine eksempler har været kompliceret ?
Løsninger der opfører sig korrekt, har hele tiden været de simpleste at
skrive.

> Når jeg taler om kompliseret, er
> det ikke et sprøgsmål om at noget er _svært_, det er et spørgsmål om
> at sammenligne med andre løsninger, f.eks. en garbage collector. En
> garbage collector giver andre problemer, men hvilke problemer er
> størst?
>

Jeg mener bestemt at garbage collection uden deterministisk objekt livstid
som _eneste_ model, sådan som det findes i Java og C#, er af et onde der er
langt større end håndteringen af resourcer i C++.
Jeg ved ikke med garbage collection generelt som et tilbud. Jeg har blot
ikke oplevet at det løser et problem som jeg har med C++.
Jeg forventer ikke at vi er enige
Jeg gider heller ikke at starte en lang religiøs diskution om det punkt.
Jeg protesterer og præciserer blot, når der bliver f.eks. bliver sagt

<citat>
I C++ skal man selv rydde op i _mange_ flere situationer, og i dette sprog
er det derfor betydelig vigtige at have destructor-funktionalitet.
<citat/>

som både er både er upræcist og blander "delete" som man selv skal kalde
sammen med destructor funktionalitet.

>
> Dit eksempel er meget homogent, idet det kun arbejder med én klasse
> i noget så simpelt som en vector.

Man kan ikke forvente andet i en nyhedsgruppe.

> At lave 100 eller 10.000 instanser
> af den samme klasse og proppe dem i en container er ikke det jeg mener
> med skalering.

Naturligvis ikke.

> Jeg tænker på mere heterogene objektsystemer; hvor det
> kan være et problem at placere ansvaret for at nedlægge et objekt;
> hvor ejerskab ikke så let lader sig placere.
>

Hvis det er tilfældet kan man f.eks. benytte reference countede smart
pointere, hvor smart pointerne har et klart ejerskab.
Sådanne kan findes færdiglavede på www.boost.org.

Venlig hilsen

Mogens Hansen



Mikkel Bundgaard (31-03-2002)
Kommentar
Fra : Mikkel Bundgaard


Dato : 31-03-02 01:18

"Mogens Hansen" <mogens_h@dk-online.dk> wrote in message
news:a85gn1$2glp$2@news.cybercity.dk...
> Ved generisk programmering forstår jeg programmering med
> generiske parametre, sådan som det f.eks. ses i STL.
> Det er også noget med compile-time polymorphy.
> Hvor finder du den form for generisk programmering i f.eks.
> Java og C# ?
Jeg var til et udemærket fordrag af Peter Sestoft, hvor han
forklarede om Generic C#, som er en udvidelse af C#. Svjh.
sagde han, at det i den nærmeste fremtid ville blive tilføjet til
sproget (sikkert et par år ), men at Microsoft var bange for, at
det ville forvirre alle VB'erne .

Se evt.
http://www.funtechs.org/talks/2001-12-19.html
(kan ikke lige finde nogle andre gode links på nettet).

Der findes svhj. også forslag til Java:
PolyJ
http://lirone.lcs.mit.edu/polyj/
GJ
http://www.research.avayalabs.com/user/wadler/pizza/gj/
men dem kender jeg ikke så meget til.
--
Mikkel Bundgaard
IT University of Copenhagen
http://officehelp.gone.dk
Codito, Ergo Sum



Mogens Hansen (31-03-2002)
Kommentar
Fra : Mogens Hansen


Dato : 31-03-02 08:04


"Mikkel Bundgaard" <mikkelbu@teliamail.dk> wrote in message
news:a85kkt$7n$1@sunsite.dk...
> "Mogens Hansen" <mogens_h@dk-online.dk> wrote in message
> news:a85gn1$2glp$2@news.cybercity.dk...
> > Ved generisk programmering forstår jeg programmering med
> > generiske parametre, sådan som det f.eks. ses i STL.
> > Det er også noget med compile-time polymorphy.
> > Hvor finder du den form for generisk programmering i f.eks.
> > Java og C# ?
> Jeg var til et udemærket fordrag af Peter Sestoft, hvor han
> forklarede om Generic C#, som er en udvidelse af C#. Svjh.
> sagde han, at det i den nærmeste fremtid ville blive tilføjet til
> sproget (sikkert et par år ), men at Microsoft var bange for, at
> det ville forvirre alle VB'erne .
>
> Se evt.
> http://www.funtechs.org/talks/2001-12-19.html
> (kan ikke lige finde nogle andre gode links på nettet).
>

Tak, jeg har ikke tidligere set så konkret beskrivelse af generics i C#.

Se
research.microsoft.com/projects/clrgen/generics.pdf

> Der findes svhj. også forslag til Java:
> PolyJ
> http://lirone.lcs.mit.edu/polyj/
> GJ
> http://www.research.avayalabs.com/user/wadler/pizza/gj/
> men dem kender jeg ikke så meget til.

Det er interessant nok.
Jeg har set lidt til Sun's bud på generic i Java - som så vidt jeg kan
vurdere på nuværende tidspunkt har et helt andet mål og konsekvenser end
templates i C++.
Både generisk programmering og aspect oriented programming syntes jeg ser
spændende ud.
Det er blot ikke en del af Java eller C#, som tingene står i dag.

Venlig hilsen

Mogens Hansen



Flemming Jensen (31-03-2002)
Kommentar
Fra : Flemming Jensen


Dato : 31-03-02 19:03


Hej Mogens

Nu kunne vi sikkert fortsætte denne diskussion i mange uger endnu
men den har nået det punkt hvor jeg tror det er begrænset hvor meget
nyt jeg vil få ud af den, memory leaks er trods alt kun et mindre
hjørne.

Der er nogle grundlæggende ting vi er uenige om, og jeg tvivler
på vi kommer det nærmere.

Du har givetvis arbejdet med C++ i mange år, og er sikkert ikke
nogen velvalgt prototype på en C++ programmør. Hvor mange C++
programmører har læst _hele_ Bjarnes bog? Jeg gætter på højest
én promille, resten har den stående. Hvor mange har læst
appendix E? måske en procent.

Hver gang jeg står med Bjarnes bog kan jeg rent fysisk mærke
hvad der er problemet. Hvis man skal læse en bog på 1000 sider
for at slippe nogenlunde fra at skrive et C++ program så siger
det mere end ord (Bogen er meget tæt skrevet og ville fylde
mange tusinde sider hvis den var skrevet i den lette stil
alle andre bøger i den størrelsesorden er skrevet i).

Man kunne så være sej og sige noget med at man bare kan lære
C++ ordentlig osv. men det holder ikke for det tager simpelthen
for lang tid. Kompleksiteten er et andet af C++'s problemer.

Da jeg først lærte Java at kende irriterede det også mig, at
der var så meget de havde fjernet. Bla. det du
skriver med den begrænsede måde man kan allokere objekter på,
men efter få uger havde jeg glemt det og aldrig savnet det siden.
Det eneste jeg virkelig savner i Java er templates, men det
er på vej, selvom jeg gruer for hvordan det bliver eftersom
de ikke har designet det ind i sproget fra starten af.

Hver gang jeg har undervist studerende i C++, som tidligere
har lært Java, er meldingen fra 95% af dem den samme - "lad os
komme tilbage til Java!" Jeg har en gammel kærlighed til C++, og
er på sin vis lidt skuffet over det, men det er C++'s problem:
Den prøver at være det hele, og det kan intet sprog være uden
at få kompleksitets problemer, der svier til den selv.

Når jeg underviser i C++, kunne du måske tænke dig at vide om
jeg lærer dem om løsningen med veldefinerede ejerskaber og
locals - det gør jeg ikke, for så langt når vi ikke. Pt.
skyldes det måske til dels at der er tale om et valgfag,
men selv dengang C++ var det gennemgående sprog på uddannelsen
(jeg underviser på datamatikeruddannelsen) nåede vi heller
ikke til det. Da jeg gik på uni var det heller ikke noget
man lærte, for noget så simplet som et programmeringssprog
måtte man da lære sig selv.

Den tid det tager at producere en veluddannet C++ programmør
er den gamle historie om de sidste 10% der koster 50%. Man
kan gøre interessante ting i C++ som f.eks. Java mangler,
men kompleksiteten er for dyr. Der er bedre økonomi i at lade folk
bruge sprog der mangler de sidste 10%, som formodentlig aldrig
vil savne.

Du har nogle steder spurgt til hvad jeg mener med at løsningen
er for kompleks - den er for kompleks fordi jeg skal tage hensyn
til noget jeg kan totalt ignorere hvis jeg har en garbage
collector. Med en garbage collector skal jeg bruge 0 sekunder på at
beskæftige mig med memory leaks, hvis C++ ikke kan matche det
er det ikke godt nok (Så har C++ naturligvis tabt på forhånd,
men det skal være _meget_ lidt løsningen skal kræve)

At undgå memory leaks i C++ baserer sig på veldefinerede
ejerskaber - det kan jeg ikke acceptere. Ejerskab er et
design-spørgsmål, og de problemer der måtte være med at
anvende et givent programmeringssprog må ikke få nogen
indflydelse på designet [Det bliver vi helt sikker ikke
enige om!]

Jeg har været glad for vores lille diskussion, det er rart
at få modstand fra en der virkelig kender C++, men af samme
grund repræsenterer du også en forsvindende lille del af
verdens C++ programmører. Jeg ved ikke om du har beskæftiget
dig så meget med C++, at du ikke kan forestille dig noget
bedre. Der kommer hele tiden nye sprog, og selvom de
også har deres problemer, kommer de fordi der problemer med
de gamle.

Der er sikkert flere af de ovenstående ting du vil betegne
som vrøvl - det kan jeg ikke bruge til så meget.


/Flemming Jensen


Mogens Hansen (31-03-2002)
Kommentar
Fra : Mogens Hansen


Dato : 31-03-02 21:05

Hej Flemming,

tak for diskutionen.
Der er sikkert en række ting vi ikke bliver enige om - så meget kan vi blive
enige om .

Jeg ville egentlig have sendt dette til dig personligt - men det kan ikke
lade sig gøre da din e-mail adresse ikke ser rigtig ud.

"Flemming Jensen" <nospam@nospam.com> wrote
>
> Hej Mogens
>

[snip]
>
> Når jeg underviser i C++, kunne du måske tænke dig at vide om
> jeg lærer dem om løsningen med veldefinerede ejerskaber og
> locals - det gør jeg ikke, for så langt når vi ikke. Pt.
> skyldes det måske til dels at der er tale om et valgfag,
> men selv dengang C++ var det gennemgående sprog på uddannelsen
> (jeg underviser på datamatikeruddannelsen) nåede vi heller
> ikke til det. Da jeg gik på uni var det heller ikke noget
> man lærte, for noget så simplet som et programmeringssprog
> måtte man da lære sig selv.
>

Jeg kan virkeligt varmt anbefale dig at kigge på bogen
Accelerated C++
Andrew Koenig and Barbara E. Moo
ISBN 0-201-70353-X
til undervisningsbrug.
Den er udviklet på baggrund af mange års erfaring med undervisning i C++
programmering.
Den er _kort_ - 323 sider inklusive index. Den dækker ikke alt, men den
dækker det meste af hvad man har brug for som applikationsprogrammør, men
ikke hvad man har brug for som biblioteksudvikler.
Bjarne Stroustrup bog "The C++ Programming Language, Third Edition" (og
Special Edition) er temmelig dækkende - det _skal_ den være, og derfor
størrelsen.
Den er temmelig anderledes end de fleste andre bøger om C++.
Den er enestående ved f.eks. at præsentere templates længe inden den
behandler new/delete og pointere.
Den bruger standard library klasser som std::string og std::vector inden
bekrebet class præsenteres.
Desuden indeholder en række meget velvalgte øvelser.

[snip]
>
> Der er sikkert flere af de ovenstående ting du vil betegne
> som vrøvl - det kan jeg ikke bruge til så meget.
>

Jeg prøver på at holde en rimelig sober og seriøs tone i mine indlæg - og
det syntes jeg generelt også du har gjort.
Men når du giver dig af med meget liberale fortolkninger af Bjarne
Stroustrup's udtalelser, prøver at belære mig om hvad du mener Bjarne
Stroustrup vil have, eller påstår at jeg er blevet forført, så kan jeg ikke
betegne det som andet end vrøvl.
Jeg afholder mig i det hele taget fra at udtale mig om hvad Bjarne
Stroustrup mener eller vil have - det kan han selv klare.
Jeg siger hvad _jeg_ mener, og henviser til Bjarne Stroustrup's eller andres
arbejde hvor jeg finder det relevant - sådan som jeg også har gjort i denne
tråd.
Jeg afholder mig fra at omtale Bjarne Stroustrup ved fornavn, på trods af at
vi har et glimrende forhold og udemærket kender hinanden personligt - jeg
skal tilbringe hele næste uge samme sted som ham.

Venlig hilsen

Mogens Hansen

PS

Jeg fandt iøvrigt lige følgende på Bjarne Stroustrup's hjemmeside:
http://www.research.att.com/~bs/bs_faq2.html#memory-leaks
jeg kan ikke huske om jeg tidligere har set det, men der er ikke nævneværdig
forskel på Bjarne Stroustrup's anbefalinger, og det jeg har sagt gennem hele
denne tråd.



Mogens Hansen (31-03-2002)
Kommentar
Fra : Mogens Hansen


Dato : 31-03-02 21:05


"Flemming Jensen" <nospam@nospam.com> wrote in message
news:3ca74062.1364852@news.cybercity.dk...


[snip]
> Med en garbage collector skal jeg bruge 0 sekunder på at
> beskæftige mig med memory leaks, hvis C++ ikke kan matche det
> er det ikke godt nok (Så har C++ naturligvis tabt på forhånd,
> men det skal være _meget_ lidt løsningen skal kræve)
>

Så brug en garbage collector sammen med C og C++:
ftp://ftp.sgi.com/other/gc/gc.html
Bl.a. gcc compileren bruger den så vidt jeg ved.

[snip]
> Jeg ved ikke om du har beskæftiget
> dig så meget med C++, at du ikke kan forestille dig noget
> bedre. Der kommer hele tiden nye sprog, og selvom de
> også har deres problemer, kommer de fordi der problemer med
> de gamle.
>

Jeg følger bestemt hele tiden med i hvad der sker inden for nye
programmeringssprog.
Jeg har f.eks. fået formel undervisning i Java og C#.
Jeg finder tanker som "generic programming", "generative programming",
"aspect oriented programming" og "intentional programming" interessante.
Programmeringssprog er for mig ikke det mest interessante - det er den
erfaring og indsigt som ligger bag programmeringssproget der er mest
interessant. Jeg finder design, udviklings process og software test
interessante. Dog kan man ikke adskille disse ting fra programmeringssprog.
Jeg håber så afgjort at der at der kommer noget bedre, der vil afløse C++.
Jeg vil finde det trist hvis C++ stadig om 30 år er den målestok andre sprog
(eller hvad det måtte være) måles i forhold til - vi er forhåbentligt blevet
reelt klogere. Om ikke andet vil vores opfattelse af hvordan man bedst
bruger C++ være ændret i forhold til i dag .
Jeg syntes ikke at f.eks. Java og C# er gode bud på en værdig afløser. Jeg
ser dem mere som værdige bud på afløsere til f.eks. Visual Basic, Delphi og
PowerBuilder - men det er en helt anden snak.

Venilg hilsen

Mogens Hansen



Lars Mosegård (31-03-2002)
Kommentar
Fra : Lars Mosegård


Dato : 31-03-02 22:42


"Mogens Hansen" <mogens_h@dk-online.dk> skrev i en meddelelse
news:a87q28$gmq$2@news.cybercity.dk...
> Jeg syntes ikke at f.eks. Java og C# er gode bud på en værdig afløser. Jeg
> ser dem mere som værdige bud på afløsere til f.eks. Visual Basic, Delphi og
> PowerBuilder - men det er en helt anden snak.
>
Hvordan definerer du en "værdig" afløser?

Fakta er at Java afløser C++ i stor stil i industrien - specielt indenfor
server-applicationer (nej, ikke kun WEB-applikationer).

Mvh
Lars



Mogens Hansen (31-03-2002)
Kommentar
Fra : Mogens Hansen


Dato : 31-03-02 08:53


"Flemming Jensen" <nospam@nospam.com> wrote in message
news:3ca5e93f.27162707@news.cybercity.dk...
> On Sat, 30 Mar 2002 13:22:58 +0100, "Mogens Hansen"
> <mogens_h@dk-online.dk> wrote:
>

> >Det korte svar:
> >Nej, du har ret objektet bliver ikke frigivet hvis man kun har en
almindelig
> >pointer til objektet (sproget _forhindrer_ ikke at man opfører sig
> >tåbeligt).
>
> At det er tåbeligt skyldes ene og alene at det kan give memory leaks.
> Det er en af grundidéerne i mine argumenter, at det ikke er
> acceptabelt at ens programmeringsstil skal dikteres af en teknikalitet
> som memory leaks. Memory leaks er sprogets problem og det er sproget
> der skal løse det.
>
> >Det lidt længere svar:
> >Hvis du har et objekt som du vil deallokere i slutningen af blokken, så
skal
> >den da ikke allokeres på heapen med mindre der er en ualmindelig god
grund
> >til det.
>
> Du tager frihed fra programmøren ved at kræve at der skal være en god
> grund, og Bjarne vil ikke have den slags, det ved du jo godt
>
> "There is no one right way to write every program - and even if there
> were there would be no way of forcing programmers to use it"
> (http://www.research.att.com/~bs/bs_faq.html#Object-Oriented-language)
>
> Problemet med de løsninger der findes i C++, på memory leak problemet,
> er netop at de _totalt_ giver køb på denne sunde tanke, som jeg er
> fuldstændig enig med Bjarne i (hvilket visse guruer bestemt ikke er!)
>
> Hvis jeg skulle svare på alle de postings der har været i forbindelse
> med denne tråd, skulle det være med Bjarnes to linier ovenfor - de
> fejer totalt løsningen med locals af banen! Man kan ganske enkelt ikke
> pålægge folk at programmere "Moderne" C++.
>

Det er pudsigt hvordan det samme udgangspunkt (de 2 linier, som du citerer
fra Bjarne Stroustrup) kan føre os til vidt forskellige konklussioner.

C++ giver muligheden for at allokere objekter statisk (global variable,
static member i klasser, static i funktioner), automatisk (på stakken
typisk) eller på heapen. Det kræver et bevidst, kvalificeret valg at gøre
det ene eller det andet, og der følger et ansvar med ethvert valg.
Jeg viste i "foo2" og "foo3" hvordan man kan allokere på heapen på en sikker
og korrekt måde, hvis man har behov for det.
Jeg viste i "foo4" at det var så meget simplere, kortere og mere effektivt
at bruge automatiske variable, når de alligevel skulle nedlægges ved enden
af scope, at der ikke er _grund_ til at gøre andet.

Java's objektmodel giver _kun_ (med undtagelse af simple indbyggede typer)
muligheden for at:
* allokere objekter på heapen
* ikke deterministisk objekt livstid (selv hvis man syntes at man har brug
for det i nogle situationer - finalize virker ikke i praksis fordi der ikke
er nogen garantier for at den bliver kaldt, sammen med det alvorlige
performance overhead det giver, og alt det grimme omkring resurection)
* påtvunget garbage collection
selv hvis man ville påtage sig ansvaret når man har et andet behov.

Hvordan du får det til at C++ påtvinger netop een måde at gøre tingene på er
mig simpelt hen en gåde. Det er jo åbenlyst forkert!
En af de ting der altid har generet mig ved Java's objekt model er netop den
begrænsning der ligger i at kun have een model for objekt allokering og
objekt livstid.

Venlig hilsen

Mogens Hansen



Mogens Hansen (26-03-2002)
Kommentar
Fra : Mogens Hansen


Dato : 26-03-02 19:12


"Flemming Jensen" <nospam@nospam.com> wrote
> On Mon, 25 Mar 2002 19:34:37 +0100, "Mogens Hansen"
> <mogens_h@dk-online.dk> wrote:

>>Hvad er der galt med en global funktion i C++ ?
>
>Det samme som der er galt med globale funktioner i et hvilket som
>helst andet sprog der bør efterlades i det netop afsluttede
>århundrede. De kobler til højre og venstre og forurener det globale
>navnerum.
>

Jeg prøver alligevel selv om det sikkert ikke fører til noget.

Kan du objektivt forklare mig og gruppen som sådan, hvordan følgende

void foo1(void)
{
FILE* f = fopen(...);
if(0 == f) return;
// do something
fclose(f);
}

kobler mere til højre og venstre, end

void foo2(void)
{
ifstream is(...);
if(!is) return;
// do something
}

uden at anvende tomme floskler som "... et hvilket som helst andet sprog der
bør efterlades i det netop afsluttede århundrede" ?

Begge funktioner kobler til en del af C++ Standard Library, og gør
programmet afhængigt af at platformen har et filsystem.

I øvrigt ligger "fopen", "fclose" og "istream" alle i "namespace std".

Jeg kan se andre ulemper ved "foo1" i forhold til "foo2" - f.eks. at man
skal _huske_ at kald "fclose" .

Kan du objektivt forklare mig og gruppen som sådan, hvordan C++ Standard
library funktioner som f.eks. "std::find" kobler mere til højre og venstre
end at anvende klasser fra C++ Standard Library som "std::string" ?

Venlig hilsen

Mogens Hansen





Jonas Meyer Rasmusse~ (26-03-2002)
Kommentar
Fra : Jonas Meyer Rasmusse~


Dato : 26-03-02 22:32

"Flemming Jensen" <nospam@nospam.com> wrote in message
news:3c9fbf20.41906378@news.cybercity.dk...
[snip]
> Jeg regner ikke nødvendigvis STL for at være "rigtig" C++. Hvis det
> ikke er objektorinteret kan det være lige så meget standard som det
> vil, det vil alligevel være usundt.

øh, med sådan en holdning skulle man så ikke programmere i noget andet end
java?
Kan du virkelig med hånden på hjertet sige at java er _rent_
objektorienteret, eller skal
jeg sige et par nøgleord som modbeviser det?

Og programmerer du i java uden at bruge de nøgleord, da de jo står for
ikke-objektorienterede ting, og derfor ifølge dig, usunde ting?

Som Mogens siger, så er det en naiv holdning at have, at objektorienteret
programmering
er den eneste vej frem.

Jonas



Bertel Lund Hansen (26-03-2002)
Kommentar
Fra : Bertel Lund Hansen


Dato : 26-03-02 22:50

Jonas Meyer Rasmussen skrev:

>Kan du virkelig med hånden på hjertet sige at java er _rent_
>objektorienteret, eller skal jeg sige et par nøgleord som modbeviser det?

Jeg vil gerne høre de nøgleord.

>Som Mogens siger, så er det en naiv holdning at have, at objektorienteret
>programmering er den eneste vej frem.

Jeg mener at det er for snævert at mene at
<indsætetellerandether> er den eneste brugbare metode.

Hovsa! Det rammer jo Mogens.

--
Bertel
http://lundhansen.dk/bertel/   FIDUSO: http://fiduso.dk/

Jonas Meyer Rasmusse~ (26-03-2002)
Kommentar
Fra : Jonas Meyer Rasmusse~


Dato : 26-03-02 22:58

"Bertel Lund Hansen" <nospam@lundhansen.dk> wrote in message
news:e5r1aucmu6cai2k974ekafv3hn0efihpv0@sunsite.auc.dk...
> Jonas Meyer Rasmussen skrev:
>
> >Kan du virkelig med hånden på hjertet sige at java er _rent_
> >objektorienteret, eller skal jeg sige et par nøgleord som modbeviser det?
>
> Jeg vil gerne høre de nøgleord.

int, double, char, byte(og hvad de ellers hedder, jeg er ikke klar over om
det er alle de primitive typer)

>
> >Som Mogens siger, så er det en naiv holdning at have, at objektorienteret
> >programmering er den eneste vej frem.
>
> Jeg mener at det er for snævert at mene at
> <indsætetellerandether> er den eneste brugbare metode.

jada, det har du helt ret i.



Bertel Lund Hansen (26-03-2002)
Kommentar
Fra : Bertel Lund Hansen


Dato : 26-03-02 23:02

Jonas Meyer Rasmussen skrev:

>int, double, char, byte(og hvad de ellers hedder, jeg er ikke klar over om
>det er alle de primitive typer)

Jeg tænkte det nok.

--
Bertel
http://lundhansen.dk/bertel/   FIDUSO: http://fiduso.dk/

Soeren Sandmann (27-03-2002)
Kommentar
Fra : Soeren Sandmann


Dato : 27-03-02 14:42

Bertel Lund Hansen <nospam@lundhansen.dk> writes:

> >Kan du virkelig med hånden på hjertet sige at java er _rent_
> >objektorienteret, eller skal jeg sige et par nøgleord som modbeviser det?
>
> Jeg vil gerne høre de nøgleord.

De primitive typer, int, double mv., er ikke objektorienterede i den
forstand at de er klasser man kan arve fra.

Exceptions er ikke et objektorienteret koncept.

> Jeg mener at det er for snævert at mene at
> <indsætetellerandether> er den eneste brugbare metode.
>
> Hovsa! Det rammer jo Mogens.

Det tvivler jeg på du kan finde belæg for i noget Mogens har skrevet.

Mads Andersen (26-03-2002)
Kommentar
Fra : Mads Andersen


Dato : 26-03-02 14:29

Fra d.e.p.java, har tilladt mig at flytte mit spørgsmål hertil.

Mogens Hansen skrev:
> Naturligvis skal man gøre rede for hvor man frigiver med "delete", når man
> har skrevet "new".
> Det nemmeste er at undlade at skrive "new" i applikationskode, og i stedet
> indkapsle det i klasser sådan som det f.eks. er gjort i C++ Standard
> library klasserne "std::string" og "std::vector".
> Kombiner det med værktøjer, der verificerer at man gør tingene rigtigt og
> man har ikke noget nævneværdigt problem.

Kan du anbefale/fortælle lidt om nogle af disse værktøjer?

Mvh. Madsie



Mogens Hansen (26-03-2002)
Kommentar
Fra : Mogens Hansen


Dato : 26-03-02 15:10


"Mads Andersen" <mads054@pop.k-net.dk> wrote

> Fra d.e.p.java, har tilladt mig at flytte mit spørgsmål hertil.
>

Tak for det

> Kan du anbefale/fortælle lidt om nogle af disse værktøjer?

På MS-Windows platformen er 3 gode bud:
* Borland CodeGuard (www.borland.com)
* NuMega BoundsChecker (www.numega.com)
* Rational Purify (www.rational.com)

Borland CodeGuard er en del af Borland C++Builder Professional og
Enterprise.
Den har jeg særligt gode erfaringer med, og vil nødigt undvære. Den er dog
hårdt bundet op på at man anvender Borlands compiler. I virkeligheden er det
blot en compiler option, der får compileren til at indsætte en række ekstra
funktionskald der validerer en hel masse, som f.eks. at "this" er gyldig, at
"dest" er stor nok inden "strcpy" etc.

NuMega BoundsChecker er 2 dele. En del der er særlig god til at validere
parametre i forhold til Win32 API'et og en del der integrerer med
compileringsprocessen i Microsoft Visual C++, så der bliver indsat
instrumenteringskode meget som CodeGuard gør.
NuMega er klart det bedste værktøj til at validere parametre i forhold til
Win32 API'et.

Rational Purify instrumenterer den færdigbyggede EXE fil, med tilhørende
DLL'er. Det har den fordel at man instrumentere kode, som man ikke har
sourcen til. Purify virker sammen med Microsoft Visual C++ på MS-Windows
platformen, og muligvis (vist ikke officielt) også Intel C++ som har et
binær resultat der ligner Microsoft Visual C++ meget.

Personligt foretrækker jeg CodeGuard, som jeg syntes giver den bedste
dækning af klassiske C++ fejl som memory-leaks, hukommelses overskrivening,
brug af frigivet hukommelse. BoundsChecker og Purify oplever jeg også som
glimrende værktøjer, som dog lidt hyppigere overser fejl, eller melder fejl
for noget der ikke er fejl.

Alle 3 værktøjer er klart anbefalelsesværdige.

Jeg så for nogle få dag siden Per Abrahamsen reklamere for et værktøj der
hedder valgrind til Linux på denne gruppe. Se
http://groups.google.com/groups?q=%22Per+Abrahamsen%22+valgrind&hl=da&selm=r
j4rjobuov.fsf%40ssv2.dina.kvl.dk&rnum=1

Venlig hilsen

Mogens Hansen



Jonas Meyer Rasmusse~ (26-03-2002)
Kommentar
Fra : Jonas Meyer Rasmusse~


Dato : 26-03-02 19:20

"Mogens Hansen" <mogens_h@dk-online.dk> wrote in message
news:3ca08129$1@lxcs1.manbw.dk...
> På MS-Windows platformen er 3 gode bud:
> * Borland CodeGuard (www.borland.com)
> * NuMega BoundsChecker (www.numega.com)
> * Rational Purify (www.rational.com)

VS.net har også indbygget et værktøj til formålet.
Jeg ved ikke om de har fået pakket det pænt ind i den endelige version, men
i Beta2(den eneste version jeg har),
er det ikke legende let, men det virker fortrinligt.

mvh Jonas



Mogens Hansen (26-03-2002)
Kommentar
Fra : Mogens Hansen


Dato : 26-03-02 20:16


"Jonas Meyer Rasmussen" <meyer_remove_@diku.dk> wrote
>
> VS.net har også indbygget et værktøj til formålet.
> Jeg ved ikke om de har fået pakket det pænt ind i den endelige version,
men
> i Beta2(den eneste version jeg har),
> er det ikke legende let, men det virker fortrinligt.
>

Hvad hedder det, og hvordan aktiveres det ?

Venlig hilsen

Mogens Hansen



Jonas Meyer Rasmusse~ (26-03-2002)
Kommentar
Fra : Jonas Meyer Rasmusse~


Dato : 26-03-02 22:05

"Mogens Hansen" <mogens_h@dk-online.dk> wrote in message
news:a7qlhv$vmh$1@news.cybercity.dk...
> Hvad hedder det, og hvordan aktiveres det ?

Hej.

Deres dokumentation skriver om det her:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vsdebug/htm
l/_core_Solving_Buffer_Overwrites_and_Memory_Leaks.asp

Jeg kan desværre ikke lige huske hvordan det lige var man fik det til at
virke, det er noget tid siden

mvh Jonas



Mads Andersen (27-03-2002)
Kommentar
Fra : Mads Andersen


Dato : 27-03-02 15:42

> > Kan du anbefale/fortælle lidt om nogle af disse værktøjer?
>
> På MS-Windows platformen er 3 gode bud:
> * Borland CodeGuard (www.borland.com)
> * NuMega BoundsChecker (www.numega.com)
> * Rational Purify (www.rational.com)

Mange tak for det fine svar.

Et værktøj jeg har leget lidt med i dag (som følge af denne diskussion) er
http://www.flipcode.com/cgi-bin/msg.cgi?showThread=12September2000-Presentin
gAMemoryManager&forum=askmid&id=-1
Det er en memory manager, som omdefinerer new, delete og de gamle C venner.
For at benytte den skal man blot inkludere dens header i sine filer. Jeg
lavede en lille test:

---8<---
#include <windows.h>

#include "mmgr.h"

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR
lpCmdLine, int nCmdShow) {
int *a = new int;
double *b = new double[120];
bool *c = new bool[10];

delete a;
delete[] b;

return 0;
}
---8<---

Når programmet terminerer, danner memory manager'en en rapport over leaks:

---8<---
1 memory leak found:

Alloc. Addr Size Addr Size
BreakOn BreakOn
Number Reported Reported Actual Actual Unused Method
Dealloc Realloc Allocated by
------ ---------- ---------- ---------- ---------- ---------- -------- -----
-- ------- ---------------------------------------------------
000005 0x00451AD0 0x0000000A 0x00451AC0 0x0000002A 0x00000008 new[] N
N main.cpp(00008)::??
---8<---

Her er altså angivet linienummer og fil for allokeringen der ikke er
frigjort.

Hvis ikke man går op i validering af parametre i forhold til Win32 API'et,
hvordan ligger dette værktøj så ift. de tre du nævnte (er der mange smarte
features man mangler)? Jeg spørg på denne måde, da jeg egentlig godt kan li'
denne memory manager, men har ikke prøvet andre løsninger.

Mvh. Madsie



Bertel Lund Hansen (25-03-2002)
Kommentar
Fra : Bertel Lund Hansen


Dato : 25-03-02 00:19

Mogens Hansen skrev:

>> I C++ skal man selv rydde op i _mange_ flere situationer ...

>Det er et almindeligt udsagn, som dog ikke bliver mere rigtigt af at blive
>gentaget.

Men heller ikke mere forkert.

>Tag et simpelt eksempel

.... som måske ikke er det mest almindelige. Her er et andet (hvor
jeg ikke har fået skrevet en destructor endnu):

class Dictionary {
   public:
      Dictionary();
      Dictionary (const Entry &ind);
      bool add (const Entry &ind);
      bool substitute (char *ud, char *ind);
      bool remove (Entry &ind);
      char *lookup (char *ind);
      void display();

   private:
      Entry *wordbook[ANTAL];
      int size;
};

Hvis man lader den slags objekter nedlægge sig selv, hænger der
en masse ubenyttet hukommelse som ikke bliver frigjort, nemlig
alt det der allokeres til indgangene.

>Man skal _ikke_ selv gøre noget som helst for at sikre at det sker.

Næ, ikke i *dit* eksempel. Men det er jo en styrke ved sproget at
man kan allokere dynamisk, og så går det galt uden destructor.

--
Bertel
http://lundhansen.dk/bertel/   FIDUSO: http://fiduso.dk/

Mogens Hansen (25-03-2002)
Kommentar
Fra : Mogens Hansen


Dato : 25-03-02 19:49


"Bertel Lund Hansen" <nospam@lundhansen.dk> wrote
>Mogens Hansen skrev:
>
>>> I C++ skal man selv rydde op i _mange_ flere situationer ...
>>Det er et almindeligt udsagn, som dog ikke bliver mere rigtigt af at blive
>>gentaget.
>
>Men heller ikke mere forkert.
>

Nej, det er blot temmeligt unuanceret.

>>Tag et simpelt eksempel
>
>... som måske ikke er det mest almindelige. Her er et andet (hvor
>jeg ikke har fået skrevet en destructor endnu):
>

Mit eksempel er bestemt almindeligt i C++ programmer. Jeg vil påstå at den
konstruktion for styring af resource allokering og frigivelse findes i de
fleste C++ programmer.

>class Dictionary {
> public:
> Dictionary();
> Dictionary (const Entry &ind);
> bool add (const Entry &ind);
> bool substitute (char *ud, char *ind);
> bool remove (Entry &ind);
> char *lookup (char *ind);
> void display();
>
> private:
> Entry *wordbook[ANTAL];
> int size;
>};
>
>Hvis man lader den slags objekter nedlægge sig selv, hænger der
>en masse ubenyttet hukommelse som ikke bliver frigjort, nemlig
>alt det der allokeres til indgangene.
>

Tak for eksemplet. Det drejer sig netop om kode-stil.
Det drejer sig ikke om hvorvidt det er muligt at lave resource leaks. Det er
naturligvis muligt.
Det drejer sig om hvorvidt det er besværligt at undgå (hvilket det ikke er),
og hvilken stil man skal bruge og undervise i for at undgå resource leaks..
I stedet for et array af pointeren kunne du have anvendt "std::vector"
klassen til "wordbook".
Så havde du dels ikke haft en fast begrænsning på størrelsen ("ANTAL") og du
skulle ikke selv implementere en destructor.

class Dictionary {
public:
Dictionary();
Dictionary (const Entry &ind);
bool add (const Entry &ind);
bool substitute (char *ud, char *ind);
bool remove (Entry &ind);
char *lookup (char *ind);
void display();

private:
std::vector<Entry> wordbook;
};


>>Man skal _ikke_ selv gøre noget som helst for at sikre at det sker.
>
>Næ, ikke i *dit* eksempel. Men det er jo en styrke ved sproget at
>man kan allokere dynamisk, og så går det galt uden destructor.
>

Kig almindelige C++ klasser som "std::vector" og "std::string", som er helt
trivielle i brugen (men ikke nødvendigvis i implementeringen).
De benytter begge dynamisk allokering, men det påtrykker ikke mig som bruger
noget som helst ansvar i forbindelse med oprydning af deres allokered.
Man skriver blot

vector<int> foo(unsigned count)
{
std::string s("Hello world");
std::vector<int> v;
for(unsigned i = 0; count != i; ++i)
v.push_back(i)
return v;
}

Den simpleste måde at undgå resource leaks i C++ er ved at lade være med at
lave dem.
Det lyder simpelt, og er det egentlig også når man lige tænker sig lidt om.



Venlig hilsen

Mogens Hansen





Bertel Lund Hansen (25-03-2002)
Kommentar
Fra : Bertel Lund Hansen


Dato : 25-03-02 22:48

Mogens Hansen skrev:

>I stedet for et array af pointeren kunne du have anvendt "std::vector"
>klassen til "wordbook".

Siger du at man bør skrive C++-programmer uden selv at allokere
hukommelse (og altså hver gang bruge indbyggede metoder i
stedet)?

--
Bertel
http://lundhansen.dk/bertel/   FIDUSO: http://fiduso.dk/

Martin Ehmsen (26-03-2002)
Kommentar
Fra : Martin Ehmsen


Dato : 26-03-02 00:44

Bertel Lund Hansen <nospam@lundhansen.dk> wrote:
>>I stedet for et array af pointeren kunne du have anvendt "std::vector"
>>klassen til "wordbook".

> Siger du at man bør skrive C++-programmer uden selv at allokere
> hukommelse (og altså hver gang bruge indbyggede metoder i
> stedet)?

Jeg vil da mene at det er den bedste fremgangsmåde. Da du så undgår selv
at lave memory-leaks osv...
Hvem har ikke prøvet at bruge timer på at debugge et program som laver
seq-faults på tilsyneladende tilfældige tidspunkter.

Martin
--
Jeg har det med min rumlige frihed som jeg har lagt mærke til at mænd
har det med deres testikler.
Jeg vugger den som et spædbarn, og tilbeder den som en gudinde.
   Smilla Jaspersen

Mogens Hansen (26-03-2002)
Kommentar
Fra : Mogens Hansen


Dato : 26-03-02 06:17


"Bertel Lund Hansen" <nospam@lundhansen.dk> wrote
> Mogens Hansen skrev:
>
> >I stedet for et array af pointeren kunne du have anvendt "std::vector"
> >klassen til "wordbook".
>
> Siger du at man bør skrive C++-programmer uden selv at allokere
> hukommelse (og altså hver gang bruge indbyggede metoder i
> stedet)?
>

Generelt ja.
I eksemplet går man ikke glip af noget funktionalitet ved at bruge
"std::vector" - det er blot nemmere.
Generelt er det en fordel at indkapsle brugen af new og delete i C++ i
klasser, som er simple at bruge på applikations niveau - sådan som det er
gjort i "std::vector" og "std::string".

Venlig hilsen

Mogens Hansen



Bertel Lund Hansen (26-03-2002)
Kommentar
Fra : Bertel Lund Hansen


Dato : 26-03-02 16:07

Mogens Hansen skrev:

>> Siger du at man bør skrive C++-programmer uden selv at allokere
>> hukommelse (og altså hver gang bruge indbyggede metoder i stedet)?

>Generelt ja.

Så må jeg nok erklære mig enig med Flemming Jensen i at C++ har
nogle værktøjer som man kan bruge eller ej.

I ethvert sprog kan det formodentlig lade sig gøre at skrive
noget der ikke er hensigtsmæssigt. Men at erklære visse
kommandoer som uanvendelige er at gøre vold på sproget.

>I eksemplet går man ikke glip af noget funktionalitet ved at bruge
>"std::vector" - det er blot nemmere.

Det er da rigtigt, men det er mindre vøæsentligt. Det er blot
plukket fra en hurtig opgave jeg har lavet.

>Generelt er det en fordel at indkapsle brugen af new og delete i C++ i
>klasser, som er simple at bruge på applikations niveau - sådan som det er
>gjort i "std::vector" og "std::string".

Måske. Det kommer an på om disse klasser er implementeret
ordentligt. Javas Stack er f.eks. baseret på en uindskrænket
Vector så man har adgang til non-stakoperationer. Det er noget
fusk.

--
Bertel
http://lundhansen.dk/bertel/   FIDUSO: http://fiduso.dk/

Mogens Hansen (26-03-2002)
Kommentar
Fra : Mogens Hansen


Dato : 26-03-02 19:12


"Bertel Lund Hansen" <nospam@lundhansen.dk> wrote

> Mogens Hansen skrev:
>
> >> Siger du at man bør skrive C++-programmer uden selv at allokere
> >> hukommelse (og altså hver gang bruge indbyggede metoder i stedet)?
>
> >Generelt ja.
>
> Så må jeg nok erklære mig enig med Flemming Jensen i at C++ har
> nogle værktøjer som man kan bruge eller ej.
>

Sådan opfatter jeg ikke hvad Flemming Jensen sagde.
Jeg syntes i højere grad at Flemming Jensen gav udtryk for at "new" og
"delete" var den væsentligste måde for applikationskode at allokere objekter
på, og det mener jeg bestemt ikke er tilfældet eller ønskeligt.

> I ethvert sprog kan det formodentlig lade sig gøre at skrive
> noget der ikke er hensigtsmæssigt. Men at erklære visse
> kommandoer som uanvendelige er at gøre vold på sproget.
>

Du misforstår og overfortolker hvad jeg siger.
Jeg har bestemt ikke erklæret visse kommandoer som uanvendelige.

> >I eksemplet går man ikke glip af noget funktionalitet ved at bruge
> >"std::vector" - det er blot nemmere.
>
> Det er da rigtigt, men det er mindre vøæsentligt. Det er blot
> plukket fra en hurtig opgave jeg har lavet.
>

Det er da væsentligt at man simpelt med anvendelse af C++ Standard Library
(f.eks. vector, list, deque) kan lave en løsning der er enklere og fjerner
åbenlyse fejlmuligheder.

> >Generelt er det en fordel at indkapsle brugen af new og delete i C++ i
> >klasser, som er simple at bruge på applikations niveau - sådan som det er
> >gjort i "std::vector" og "std::string".
>
> Måske. Det kommer an på om disse klasser er implementeret
> ordentligt. Javas Stack er f.eks. baseret på en uindskrænket
> Vector så man har adgang til non-stakoperationer. Det er noget
> fusk.
>

Hvad har det med C++ og resource håndtering at gøre ?

Venlig hilsen

Mogens Hansen



Bertel Lund Hansen (26-03-2002)
Kommentar
Fra : Bertel Lund Hansen


Dato : 26-03-02 20:30

Mogens Hansen skrev:

>> Måske. Det kommer an på om disse klasser er implementeret
>> ordentligt. Javas Stack er f.eks. baseret på en uindskrænket
>> Vector så man har adgang til non-stakoperationer. Det er noget
>> fusk.

>Hvad har det med C++ og resource håndtering at gøre ?

Det var dette her der var væsentligt:

   Det kommer an på om disse klasser er implementeret
   ordentligt.

--
Bertel
http://lundhansen.dk/bertel/   FIDUSO: http://fiduso.dk/

Dennis Thrysøe (25-03-2002)
Kommentar
Fra : Dennis Thrysøe


Dato : 25-03-02 08:11

Hejsa,

Jeg vil påstå, at hvis en destructor er *nødvendig*, så er der lavet
noget dårligt design et eller andet sted.

Men hvis man virkligt vil, kan man bare lave en destructor() metode og
kalde den - ingen problem.

I dit tilfælde ville jeg have lavet en Factory som en rigtig singleton
til at oprette objekterne. Denne Factory kunne så f.eks. holde styr på
hvilke objekter den havde lavet. Men denne slags konstruktioner giver
mulighed for memory leaks.

-dennis


Martin Ehmsen wrote:
> Hej...
>
> Jeg har er løbet ind i et problem (som jeg har løst , men det gav
> anledning til undren over hvorfor klasser i Java ikke kan have
> destructors som de kendes fra C++.
> Den forklaring som man oftest støder ind i, er at destructors i C++
> bruges til at frigøre hukommelse som ikke længere skal bruges. Dette
> problem har man jo ikke i Java.
> Men nu kan destructors også bruges til andet. Jeg havde fx et statisk
> felt i en klasse, som blev opdateret når nye objekter af klassen blev
> oprettet. Men samtidig ville jeg også gerne have feltet opdateret når
> objekter blev nedlagt. I sådan en situation ville destructors være en
> let løsning.
> Man kunne selvfølgelig vælge at lægge koden i: protected void finalize()
> Som så ville fungerer som en slags destructor, men finalize() bliver kun
> kaldt når garbage collector'en har rydet op, og det er der jo ingen
> garanti for hvornår den gør.
> Jeg ville høre om der er andre som også har siddet med problemet og
> hvordan I evt. løste det. Hvis der også er nogen som har en god
> forklaring på hvorfor Java ikke har destructors, så vil jeg da også
> gerne høre den.
>
> Martin


Mogens Hansen (27-03-2002)
Kommentar
Fra : Mogens Hansen


Dato : 27-03-02 23:08


"Dennis Thrysøe" <dt@netnord.dk> wrote

>
> Jeg vil påstå, at hvis en destructor er *nødvendig*, så er der lavet
> noget dårligt design et eller andet sted.
>

Strengt taget er meget få sprogkonstruktioner _nødvendige_.
Man kan ikke lave noget f.eks. Java eller C++ som man ikke kan lave i C
eller assembler, men en passende indsats.
Det interessante er om en sprogkonstruktion løser forekommende problemer på
en mere effektiv eller sikker måde.

Frigivelse af resourcer er et almindeligt forekommende problem, og det er
ikke ualmindeligt at man har behov for at _vide_ hvornår det sker.
Derfor findes f.eks.:
java.sql.Connection.close()
java.io.FileInputStream.close()

Er det dårligt design at ovenstående Java klasser har behov for at kunne
frigive resourcer ?

I det Java lignende sprog C# har Microsoft lavet et interface (IDisposable)
som kan benyttes med sprog konstruktionen "using statement" (som blev
tilføjet efter Beta 1), for at kunne sikre at objekter får mulighed for at
frigive deres resourcer (ikke memory) på et velkendt tidspunkt.

F.eks.

using System.Drawing;
class a
{
public static void Main()
{
using (Font MyFont = new Font("Arial", 10.0f), MyFont2 = new
Font("Arial", 10.0f))
{
// use MyFont and MyFont2
} // compiler will call Dispose on MyFont and MyFont2

Font MyFont3 = new Font("Arial", 10.0f);
using (MyFont3)
{
// use MyFont3
} // compiler will call Dispose on MyFont3

}
}


> I dit tilfælde ville jeg have lavet en Factory som en rigtig singleton
> til at oprette objekterne. Denne Factory kunne så f.eks. holde styr på
> hvilke objekter den havde lavet. Men denne slags konstruktioner giver
> mulighed for memory leaks.
>

Jeg kan ud fra din beskrivelse nemt se hvordan man med en Factory kan holde
styr på hvormange objekter der er oprettet.
Kan du skitsere hvordan en Factory kan holde styr på hvornår objekter bliver
nedlagt ?
Man er nok også nødt til at beskrive hvad "nedlagt" betyder, f.eks.:
* F.eks. at der ikke er flere referencer til objektet (har Garbage
Collectoren kørt, er "finalize" udført ?)
* Applikationen fortæller at et givent objekt ikke længere er logisk
gyldigt (selv om der muligvis stadig er referencer til det)

Venlig hilsen

Mogens Hansen



Dennis Thrysøe (28-03-2002)
Kommentar
Fra : Dennis Thrysøe


Dato : 28-03-02 12:59



Mogens Hansen wrote:
> "Dennis Thrysøe" <dt@netnord.dk> wrote
>
>
>>Jeg vil påstå, at hvis en destructor er *nødvendig*, så er der lavet
>>noget dårligt design et eller andet sted.
>>
>
>
> Strengt taget er meget få sprogkonstruktioner _nødvendige_.
> Man kan ikke lave noget f.eks. Java eller C++ som man ikke kan lave i C
> eller assembler, men en passende indsats.
> Det interessante er om en sprogkonstruktion løser forekommende problemer på
> en mere effektiv eller sikker måde.
>
> Frigivelse af resourcer er et almindeligt forekommende problem, og det er
> ikke ualmindeligt at man har behov for at _vide_ hvornår det sker.
> Derfor findes f.eks.:
> java.sql.Connection.close()
> java.io.FileInputStream.close()
>
> Er det dårligt design at ovenstående Java klasser har behov for at kunne
> frigive resourcer ?

Nej, det er netop godt design, efter min mening. Jeg mener at
destructorer (i de sprog hvor de findes) bruges forkert for ofte. Hvis
man gerne vil have et destructor-agtigt fænomen i sin Java objektmodel,
synes jeg man skal lave det, som f.eks. close() metoderne du nævner. Det
er der ikke noget i vejen for.

>>I dit tilfælde ville jeg have lavet en Factory som en rigtig singleton
>>til at oprette objekterne. Denne Factory kunne så f.eks. holde styr på
>>hvilke objekter den havde lavet. Men denne slags konstruktioner giver
>>mulighed for memory leaks.
>>
>
>
> Jeg kan ud fra din beskrivelse nemt se hvordan man med en Factory kan holde
> styr på hvormange objekter der er oprettet.
> Kan du skitsere hvordan en Factory kan holde styr på hvornår objekter bliver
> nedlagt ?

Det er her, de memory leaks jeg nævner, kommer ind i billedet. Man skal
selv "invalidere" dem igen. (Jeg ER godt klar over, at der ikke er
destructorer i Java ;). Man implementerer en destruct() metode på sine
objekter, som sørger for at fortælle Factory instansen, at det ikke
længere er gyldigt.

> Man er nok også nødt til at beskrive hvad "nedlagt" betyder, f.eks.:
> * F.eks. at der ikke er flere referencer til objektet (har Garbage
> Collectoren kørt, er "finalize" udført ?)

Det skulle så i giver fald være, når objektet ikke er semantisk
gyldigt/ønsket mere.

> * Applikationen fortæller at et givent objekt ikke længere er logisk
> gyldigt (selv om der muligvis stadig er referencer til det)

Netop.

Men vi er ude på et meget generelt plan, hvor det er svært at diskutere
konkrete fremgangsmåder. Mit forslag vil være fint under nogen
omstændigheder, men ikke under andre. Sådan er det jo altid med software
design...


-dennis


Mogens Hansen (28-03-2002)
Kommentar
Fra : Mogens Hansen


Dato : 28-03-02 23:51


"Dennis Thrysøe" <dt@netnord.dk> wrote
>
>
> Mogens Hansen wrote:
> > "Dennis Thrysøe" <dt@netnord.dk> wrote
> >
> >
> >>Jeg vil påstå, at hvis en destructor er *nødvendig*, så er der lavet
> >>noget dårligt design et eller andet sted.
> >>
> >
> >
> > Strengt taget er meget få sprogkonstruktioner _nødvendige_.
> > Man kan ikke lave noget f.eks. Java eller C++ som man ikke kan lave i C
> > eller assembler, men en passende indsats.
> > Det interessante er om en sprogkonstruktion løser forekommende problemer

> > en mere effektiv eller sikker måde.
> >
> > Frigivelse af resourcer er et almindeligt forekommende problem, og det
er
> > ikke ualmindeligt at man har behov for at _vide_ hvornår det sker.
> > Derfor findes f.eks.:
> > java.sql.Connection.close()
> > java.io.FileInputStream.close()
> >
> > Er det dårligt design at ovenstående Java klasser har behov for at kunne
> > frigive resourcer ?
>
> Nej, det er netop godt design, efter min mening. Jeg mener at
> destructorer (i de sprog hvor de findes) bruges forkert for ofte.
[snip]

Når jeg læser hvad du skriver, kan jeg ikke forstå hvad du mener.
Mener du f.eks.:
* Destructorne laver ofte noget andet end hvad de oprindeligt var designet
til, og det forvirrer
* Det er besværligt at man skal skrive destructorer
* At de skjuler for megt af hvad der faktisk foregår for applikations
udvikleren (f.eks. af filen lukkes)
* Det besværligt ved at kalde delete i C++ (sammen med den ikke
ualmindelige sammenblanding mellem delete og destructor)
Kan du give et konkret eksempel på hvordan destructorer ofte bruges forkert.

Jeg har svært ved at se at destructorer (i C++) ikke hjælper med at gøre det
nemmere at huske at frigive resource, end Java's "close" idiom.
Hvis jeg skriver et lille eksempel, hvor man åbner 2 filer, gør noget der
kan smide exceptions og skal lukke filen i såvel C++ og Java (som jeg ikke
er specielt god til, så korriger gerne min kode hvis den er unfair eller
urealistisk), så forekommer det mig at koden bliver kortere og sikrere i C++
pga. destructorne end i Java hvor man skal huske at kalde close på de
BufferedReader der måtte være blevet åbnet.

<C++ eksempel>
#include <fstream>
#include <iostream>
#include <exception>
#include <cstdlib>

using namespace std;

void might_throw(istream& is)
{
if(!is) {
throw runtime_error("stream not ok");
}
}

int main(void)
{
try {
ifstream in1("test1.txt");
ifstream in2("test2.txt");
in1.exceptions(ios_base::badbit | ios_base::failbit);
in2.exceptions(ios_base::badbit | ios_base::failbit);
might_throw(in1);
might_throw(in2);
}
catch(exception& x) {
cerr << x.what() << endl;
return EXIT_FAILURE;
}
}
<C++ eksempel/>

<Java eksempel>
package test;

import java.io.*;
import java.lang.*;

public class Application {

public static void MightThrow(Object o) throws NullPointerException {
if(null == o) {
throw new NullPointerException("o = null");
}
}

public static void main(String[] args) {
try {
BufferedReader in1 = null;
BufferedReader in2 = null;
try {
in1 =
new BufferedReader(
new InputStreamReader(
new FileInputStream("test1.txt")));
MightThrow(in1);
in2 =
new BufferedReader(
new InputStreamReader(
new FileInputStream("test2.txt")));
MightThrow(in2);
}
finally {
if(null != in1) {
in1.close();
}
if(null != in2) {
in2.close();
}
}
}
catch(IOException e) {
System.out.println("IO Exception");
}
}
}
<Java eksempel/>


Anvendelsen af destructorne i ovenstående C++ eksempel for mig et udtryk for
godt design: det er nemt, fejlsikkert, kort at skrive og effektivt.

Jeg er godt med på Java ikke har destructorer og det medfører at i Java
gøres tingene på en anden måde (f.eks. med "try/finally" og "close" metoder,
men helst ikke "finalize").
Men derfra og så til at "destructorer bruges forkert for ofte", og "hvis en
destructor er *nødvendig*, så er der lavet noget dårligt design et eller
andet sted" det kan jeg ikke umiddelbart forstå.
Jeg kan forstå at et design som skal implementeres i Java hvor destructorer
eller destructor lignende funktionalitet er nødvendige er uhensigtsmæssigt.


Venlig hilsen

Mogens Hansen



Dennis Thrysøe (01-04-2002)
Kommentar
Fra : Dennis Thrysøe


Dato : 01-04-02 13:24

Mogens Hansen wrote:
> "Dennis Thrysøe" <dt@netnord.dk> wrote
>>
>>Mogens Hansen wrote:
>>
>>>"Dennis Thrysøe" <dt@netnord.dk> wrote
>>>Er det dårligt design at ovenstående Java klasser har behov for at kunne
>>>frigive resourcer ?
>>
>>Nej, det er netop godt design, efter min mening. Jeg mener at
>>destructorer (i de sprog hvor de findes) bruges forkert for ofte.
>
> [snip]
>
> Når jeg læser hvad du skriver, kan jeg ikke forstå hvad du mener.
> Mener du f.eks.:
> * Destructorne laver ofte noget andet end hvad de oprindeligt var designet
> til, og det forvirrer
> * Det er besværligt at man skal skrive destructorer
> * At de skjuler for megt af hvad der faktisk foregår for applikations
> udvikleren (f.eks. af filen lukkes)

"All of the above"

> * Det besværligt ved at kalde delete i C++ (sammen med den ikke
> ualmindelige sammenblanding mellem delete og destructor)

Det har jeg ikke noget forhold til.

> Kan du give et konkret eksempel på hvordan destructorer ofte bruges forkert.

Jeg har set destructorer brugt på en uhensigtsmæssig måde, rent
designmæssigt, flere gange. Typisk drejer det sig om - som du nævner -
at der laves alverdens cirkustricks i destructoren. Objektet
afregistreres andre steder i objektmodellen mv. Det er måske ikke
destructorernes (konceptets) skyld, men de gør det muligt.

> Jeg har svært ved at se at destructorer (i C++) ikke hjælper med at gøre det
> nemmere at huske at frigive resource, end Java's "close" idiom.

Der mener jeg heller ikke der er nogen synderlig forskel. I begge
tilfælde skal man explicit gøre noget, hvis man vil af med objekterne.

Den umiddelbare forskel er så, at I Java (close() idiomet, som du kalder
det) er det en semantisk nedlæggelse. Hvis man glemmer close er der en
semantisk fejl i programet. Hvis man glemmer at nedlægge et objekt i C++
er der måske en semantisk fejl, og man skal nok også forvente en
runtime-fejl / et stort memory forbrug.

> Hvis jeg skriver et lille eksempel, hvor man åbner 2 filer, gør noget der
> kan smide exceptions og skal lukke filen i såvel C++ og Java (som jeg ikke
> er specielt god til, så korriger gerne min kode hvis den er unfair eller
> urealistisk), så forekommer det mig at koden bliver kortere og sikrere i C++
> pga. destructorne end i Java hvor man skal huske at kalde close på de
> BufferedReader der måtte være blevet åbnet.

C++ koden er ihvertfald lidt kortere. For mig at se er de lige sikre,
som du har skrevet dem.

> Anvendelsen af destructorne i ovenstående C++ eksempel for mig et udtryk for
> godt design: det er nemt, fejlsikkert, kort at skrive og effektivt.

Jeg er ikke uenig.

> Jeg er godt med på Java ikke har destructorer og det medfører at i Java
> gøres tingene på en anden måde (f.eks. med "try/finally" og "close" metoder,
> men helst ikke "finalize").
> Men derfra og så til at "destructorer bruges forkert for ofte", og "hvis en
> destructor er *nødvendig*, så er der lavet noget dårligt design et eller
> andet sted" det kan jeg ikke umiddelbart forstå.

Her mener jeg egentligt ikke som sproglige konstruktioner. Mit besyv gik
på de designmæssige overvejelser. Hvis et design kun fungerer i kraft af
eksistensen af destructorer, skal man nok overveje det lidt endnu.

> Jeg kan forstå at et design som skal implementeres i Java hvor destructorer
> eller destructor lignende funktionalitet er nødvendige er uhensigtsmæssigt.

Ja og vendt på hovedet (som du siger): I C++ er det nemt nok at løse
problemerne med destructorer. Man skal bare tænke sig om.

Men: What else is new? ;)


-dennis


Mogens Hansen (01-04-2002)
Kommentar
Fra : Mogens Hansen


Dato : 01-04-02 15:38


"Dennis Thrysøe" <dt@netnord.dk> wrote
> Mogens Hansen wrote:

>
> > Kan du give et konkret eksempel på hvordan destructorer ofte bruges
forkert.
>
> Jeg har set destructorer brugt på en uhensigtsmæssig måde, rent
> designmæssigt, flere gange. Typisk drejer det sig om - som du nævner -
> at der laves alverdens cirkustricks i destructoren. Objektet
> afregistreres andre steder i objektmodellen mv.

Hvad er der galt i det set fra et _design_ synspunkt.
Tag f.eks. bidirektionelle associationer, sådan som de kendes fra UML
diagrammer.
Hvis et objekt ikke længere findes (logisk og/eller fysisk), skal alle de
objekter der hidtil har været associeret med det døende objekt have det at
vide så associationen kan blive brudt.
I C++ kan det meget nemt implementeres fornuftigt i destructoren.
Det kan vist ikke angribes relevant fra et design synspunkt.

>
> > Jeg har svært ved at se at destructorer (i C++) ikke hjælper med at gøre
det
> > nemmere at huske at frigive resource, end Java's "close" idiom.
>
> Der mener jeg heller ikke der er nogen synderlig forskel. I begge
> tilfælde skal man explicit gøre noget, hvis man vil af med objekterne.
>

Prøv lige at kigge på mine eksempler een gang til.
I Java eksemplet skal man explicit kalde "close", for at gøre det af med
objektet.
I C++ eksemplet skal man ingenting gøre.

> Den umiddelbare forskel er så, at I Java (close() idiomet, som du kalder
> det) er det en semantisk nedlæggelse. Hvis man glemmer close er der en
> semantisk fejl i programet. Hvis man glemmer at nedlægge et objekt i C++
> er der måske en semantisk fejl, og man skal nok også forvente en
> runtime-fejl / et stort memory forbrug.
>

Prøv at kigge på mine eksempler een gang til.
I C++ eksemplet er der _ingen_ mulighed for at glemme at nedlægge
objekterne.

> > Hvis jeg skriver et lille eksempel, hvor man åbner 2 filer, gør noget
der
> > kan smide exceptions og skal lukke filen i såvel C++ og Java (som jeg
ikke
> > er specielt god til, så korriger gerne min kode hvis den er unfair eller
> > urealistisk), så forekommer det mig at koden bliver kortere og sikrere i
C++
> > pga. destructorne end i Java hvor man skal huske at kalde close på de
> > BufferedReader der måtte være blevet åbnet.
>
> C++ koden er ihvertfald lidt kortere. For mig at se er de lige sikre,
> som du har skrevet dem.
>

Prøv at kigge på mine eksempler een gang til.
Java koden giver _mulighed_ for at glemme at kalde "close", fordi det skal
gøres explicit.
C++ koden giver _ingen_ mulighed for at glemme at nedlægge objekterne.

>
> Her mener jeg egentligt ikke som sproglige konstruktioner. Mit besyv gik
> på de designmæssige overvejelser. Hvis et design kun fungerer i kraft af
> eksistensen af destructorer, skal man nok overveje det lidt endnu.
>

Objekter der har et endeligt livsforløb er almindelige i den virkelige
verden.
Tag en "person" objekt, eller et "faktura" objekt. Sådanne objekters
semantik har da en klar start på livet, et livsforløb og en klar slutning på
livet.
Tag en dialog boks i en GUI (den kan naturligvis bare blive garbage
collected, når det passer systemet).
Tag en programmeringsteknisk detalje som en låsning af en Mutex i
multithreaded programmering. Man tager låsen, laver hvad man vil i det
sikrede område og frigiver herefter låsen. Frigivelsen af låsen er
_essentiel_ for programmets korrekte opførsel.
Der er _intet_ usundt i at basere sig på destructorere i sådanne eksempler.
Specielt ved reservering af Mutex'en (og andre resourcer) er det rigtigt
_sundt_ at basere sit design på destructorer - det er simpelt at
programmere, og efterlader _ingen_ mulighed for at programmøren kan
_glemme_ noget. Dette gælder naturligvis for C++, og _ikke_ for Java.
Det illustrerer også at sproguafhængige design ikke giver mening. F.eks.
spiller objekt livstidsmodellen for implementeringsteknologien en væsentlig
rolle for designet.
I C++ har objekter et deterministisk livsforløb, hvor det fysiske og
semantiske liv er knyttet sammen. Objekter overlever ikke processen som de
lever i.
I Java har objekter egentlig ikke nogen fysisk ende på livet - de bliver
måske garbage collected på et tidspunkt når der ikke er flere referencer til
objektet. De kan have en semantisk ende på livet (som f.eks. "close"
idiomet).
I CORBA har (persistente) objekter en semantisk ende på livet, som er
uafhængig af levetiden for den process objektet (måske) findes i.

>
> Men: What else is new? ;)
>

Tja, det kan du have ret i

Venlig hilsen

Mogens Hansen







Dennis Thrysøe (02-04-2002)
Kommentar
Fra : Dennis Thrysøe


Dato : 02-04-02 07:15



Mogens Hansen wrote:
> "Dennis Thrysøe" <dt@netnord.dk> wrote
>
>>Mogens Hansen wrote:
>
>
>>>Kan du give et konkret eksempel på hvordan destructorer ofte bruges
>>
> forkert.
>
>>Jeg har set destructorer brugt på en uhensigtsmæssig måde, rent
>>designmæssigt, flere gange. Typisk drejer det sig om - som du nævner -
>>at der laves alverdens cirkustricks i destructoren. Objektet
>>afregistreres andre steder i objektmodellen mv.
>
>
> Hvad er der galt i det set fra et _design_ synspunkt.
> Tag f.eks. bidirektionelle associationer, sådan som de kendes fra UML
> diagrammer.
> Hvis et objekt ikke længere findes (logisk og/eller fysisk), skal alle de
> objekter der hidtil har været associeret med det døende objekt have det at
> vide så associationen kan blive brudt.
> I C++ kan det meget nemt implementeres fornuftigt i destructoren.
> Det kan vist ikke angribes relevant fra et design synspunkt.

Enig. Det er jo så også kun ét eksempel. Jeg snakkede om en *tendens*,
ikke at destructorer altid var af det onde. Tvært imod synes jg mange
gange de letter implementeringen.

Min kommentar skulle egentligt mere eller mindre retorisk - ihvertfald
for dem med erfaring inden for software design.

>>>Jeg har svært ved at se at destructorer (i C++) ikke hjælper med at gøre
>>
> det
>
>>>nemmere at huske at frigive resource, end Java's "close" idiom.
>>
>>Der mener jeg heller ikke der er nogen synderlig forskel. I begge
>>tilfælde skal man explicit gøre noget, hvis man vil af med objekterne.
>>
>
>
> Prøv lige at kigge på mine eksempler een gang til.
> I Java eksemplet skal man explicit kalde "close", for at gøre det af med
> objektet.
> I C++ eksemplet skal man ingenting gøre.

Okay, fair nok. Det gør dog ikke, at man lykkeligt kan lade være med at
være bevidst om destructorer - især ikke, hvis de "gør noget".

>>>Hvis jeg skriver et lille eksempel, hvor man åbner 2 filer, gør noget
>>
> der
>
>>>kan smide exceptions og skal lukke filen i såvel C++ og Java (som jeg
>>
> ikke
>
>>>er specielt god til, så korriger gerne min kode hvis den er unfair eller
>>>urealistisk), så forekommer det mig at koden bliver kortere og sikrere i
>>
> C++
>
>>>pga. destructorne end i Java hvor man skal huske at kalde close på de
>>>BufferedReader der måtte være blevet åbnet.
>>
>>C++ koden er ihvertfald lidt kortere. For mig at se er de lige sikre,
>>som du har skrevet dem.
>>
> Prøv at kigge på mine eksempler een gang til.
> Java koden giver _mulighed_ for at glemme at kalde "close", fordi det skal
> gøres explicit.
> C++ koden giver _ingen_ mulighed for at glemme at nedlægge objekterne.

Det ser ud til, at vi lægger vægten på forskellige ting. Diskussionen
med Flemming omkring den konkrete implementering af desctructorer i C++,
synes jeg er fyldestgørende. Den vil jeg ikke også kaste mig us i!

>>Her mener jeg egentligt ikke som sproglige konstruktioner. Mit besyv gik
>>på de designmæssige overvejelser. Hvis et design kun fungerer i kraft af
>>eksistensen af destructorer, skal man nok overveje det lidt endnu.
>>
>
> Objekter der har et endeligt livsforløb er almindelige i den virkelige
> verden.
> Tag en "person" objekt, eller et "faktura" objekt. Sådanne objekters
> semantik har da en klar start på livet, et livsforløb og en klar slutning på
> livet.

Ja, men om der implicit (eller eksplicit) kaldes en destructor, eller om
referencen til objektet bare slettes er jeg som koder ret ligeglad med.
Bare den tekniske side af sagen (resource-forbrug mv.) også tages hånd om.

Hvis C++ fungerer som du siger - altså med implicit kaldte destructorer
- så er der vel ikke i praksis nogen forskel på håndteringen i Java og C++?

Ikke, selvfølgelig, med mindre du vil have lavet *andet* end at nedlægge
objektet i destructoren. Det kan være ok - men det er det ikke altid,
efter min mening.

> Tag en dialog boks i en GUI (den kan naturligvis bare blive garbage
> collected, når det passer systemet).

Tjah. Hvis ikke man skal bruge den mere, og derfor ikke refererer den
mere - så bør den vel frigives.

> Tag en programmeringsteknisk detalje som en låsning af en Mutex i
> multithreaded programmering. Man tager låsen, laver hvad man vil i det
> sikrede område og frigiver herefter låsen. Frigivelsen af låsen er
> _essentiel_ for programmets korrekte opførsel.

Dette kan (også) løses på mange (andre) måder. Jeg synes f.eks. Java's
løsning er okay.

> Der er _intet_ usundt i at basere sig på destructorere i sådanne eksempler.
> Specielt ved reservering af Mutex'en (og andre resourcer) er det rigtigt
> _sundt_ at basere sit design på destructorer - det er simpelt at
> programmere, og efterlader _ingen_ mulighed for at programmøren kan
> _glemme_ noget. Dette gælder naturligvis for C++, og _ikke_ for Java.

Lige præcis for mutexen (eller monitoren, som det jo ville være) er der
vel taget hånd om det i Java med forskellige forekomster af
"synchronized" og den slags.

> Det illustrerer også at sproguafhængige design ikke giver mening. F.eks.
> spiller objekt livstidsmodellen for implementeringsteknologien en væsentlig
> rolle for designet.

Det burde det ikke.

> I C++ har objekter et deterministisk livsforløb, hvor det fysiske og
> semantiske liv er knyttet sammen. Objekter overlever ikke processen som de
> lever i.
> I Java har objekter egentlig ikke nogen fysisk ende på livet - de bliver
> måske garbage collected på et tidspunkt når der ikke er flere referencer til
> objektet. De kan have en semantisk ende på livet (som f.eks. "close"
> idiomet).

ja, eller bare den simple tilstand, at man ikke har en reference til dem
længere, og derfor ikke kan få fat i dem igen. Det er rigeligt til mig.
Jeg er ligeglad med hvornår hukommelsen er fri osv. Det har som regel
intent med løsningen af min opgave at gøre.

Og hvis det havde det (med løsningen at gøre) så havde jeg nok brugt
C++. Men nu bevæger vi os ind på diskussionen om "the right tool for the
right job".

> I CORBA har (persistente) objekter en semantisk ende på livet, som er
> uafhængig af levetiden for den process objektet (måske) findes i.

Aha.



-dennis


Flemming Jensen (02-04-2002)
Kommentar
Fra : Flemming Jensen


Dato : 02-04-02 20:20

On Tue, 02 Apr 2002 08:15:21 +0200, =?ISO-8859-1?Q?Dennis_Thrys=F8e?=
<dt@netnord.dk> wrote:

>Jeg er ligeglad med hvornår hukommelsen er fri osv. Det har som regel
>intent med løsningen af min opgave at gøre.

Min oplevelse af at bruge Java og skulle overlade det til garbage
collectoren er for det meste den samme. Hvis det, at et objekt skal
dø kun er ensbetydende med at den lagerplads den optager frigives
er jeg ligeglad med hvornår det konkret sker. I de situationer er
en garbage collector en fuldstændig tranparent løsning i forhold
til hvad jeg laver - jeg skal overhovedet ikke bekymre mig om det!

Men der er jo altid undtagelserne. Hvis et objekt råder over en
resource som det er væsentlig for mig bliver frigivet når objektet
ikke længere bruges kan jeg ikke nøjes med non-determinismen i en
garbage collector, jeg er nød til eksplicit at kunne sige "dø" til
et objekt. I Java er man altid nød til at implementere denne
determinisme selv, ved at lave en "dø"-metode man kalder på objektet,
(det man kunne kalde close-idiomet) der frigiver den pågælde resource.
At objektet ikke er helt dødt, at dets lagerplads ikke er frigivet, er
stadig uvæsentligt for mig, det drejerde sig kun om den resource jeg
ville have frigivet ved dets død. I C++ svarer det nogenlunde til at
man skulle kalde destructoren selv, i begge sprog slipper man ikke for
at lave en "funktion" i objektet der frigiver resourcen. Forskellen er
at man i C++ ofte kan lave det mere elegant, fordi man ikke eksplicit
skal foretage kaldet, man kan "bare" lade objektet være en local,
så sker det automatisk (man kan naturligvis ikke _altid_ gøre
dem til locals, men jeg kan forstå at det ofte er tilfældet)
når man forlader dens scope. Dermed bliver destructionen transparent
i forbindelse med anvendelsen. Vi har tidligere haft en diskussion af
hvor lidt eller hvor meget man skal sno sig for at bruge denne
løsning, det synes jeg vi skal lade ligge.

Jeg ville gerne have begge dele i det samme sprog, men da langt
de fleste objekter jeg laver ikke har resourcer ud over den
lagerplads de selv optager føler jeg at en garbage collector
er vigtigere for mig. Så må jeg leve med (lidt) ekstra arbejde
i forbindelse med de situationer hvor der skal frigives en
resource. close-idiomet ville man naturligvis gerne være foruden,
men man må jo vælge mellem onderne. Det er jo meget rart at
jeg i Java _aldrig_ skal bekymre mig om destruction af objekter
så længe det kun er lagerplads det drejer sig om.


Man kan sige det lidt firkantet:

I Java kræver det ingen indsats at undgå memory leaks, men det kræver
en del arbejde at undgå andre former for resource leaks (close-
idiomet)

I C++ kræver det en indsats at undgå memory leaks, men ifht. Java
er det ofte enklere at undgå andre former for resource leaks.


Man kan også beskrive det på en anden måde:

Hvis man tager udgangspunkt i C++, og siger at det er lige nemt at
undgå begge former for resource leaks, har man i Java totalt
fjernet memory leaks på bekostning af at deterministiks (partiel)
destruktion skal laves manuelt.

Man må så gøre op med sig selv om man synes det er en god handel!


/Flemming Jensen


Jonas Meyer Rasmusse~ (03-04-2002)
Kommentar
Fra : Jonas Meyer Rasmusse~


Dato : 03-04-02 15:43

nospam@nospam.com (Flemming Jensen) writes:

> Man kan sige det lidt firkantet:
>
> I Java kræver det ingen indsats at undgå memory leaks, men det kræver
> en del arbejde at undgå andre former for resource leaks (close-
> idiomet)
>
> I C++ kræver det en indsats at undgå memory leaks, men ifht. Java
> er det ofte enklere at undgå andre former for resource leaks.

Nu holder jeg mig generelt fra java, hvis jeg kan slippe fra det(det kan jeg ikke),
men min konklusion udfra det du siger, og udfra resten af tråden må være følgende..

I C++ kræver det lige stor(lille!) indsats at undgå enhver form for
resource leaks. Mogens har vist at det kan gøres sikkert, hvis man kender
sit sprog ordentligt. Java har problemer med andre resourcer en hukommelse,
og det kan da få en til at overveje, om C++ så ikke har en styrke der?
Når du først har lært at benytte C++ ordentligt, så kan du kode _sikkert_..
med _både_ hukommelse og resourcer. I java kan du _ikke_ kode usikkert med
hukommelsen, men tilgengæld vil du _altid_ være bundet af at du selv skal sørge
for at frigive resourcer som ikke er hukommelse.

Altså må C++ for den erfarne programmør være mere sikkert, fordi programmøren
_ved_ hvordan man programmerer moderne C++, og der ved kan sikre at _alle_
resourcer bliver frigivet?

Problemet med manglende håndtering til nedlæggelse af resourcer i java er vel i og
for sig _præcis_ det samme som "problemet" med new/delete i C++?


mvh
Jonas Meyer Rasmussen


Flemming Jensen (03-04-2002)
Kommentar
Fra : Flemming Jensen


Dato : 03-04-02 18:11

On 03 Apr 2002 16:43:07 +0200, Jonas Meyer Rasmussen
<meyer@ivalde.diku.dk> wrote:

>I C++ kræver det lige stor(lille!) indsats at undgå enhver form for
>resource leaks. Mogens har vist at det kan gøres sikkert, hvis man kender
>sit sprog ordentligt. Java har problemer med andre resourcer en hukommelse,
>og det kan da få en til at overveje, om C++ så ikke har en styrke der?

Det ville C++ have hvis det du skriver holder 100%, men det er altid
undtagelserne der ødelægger et klart billede af det.

Jeg har ingen konkrete tal, så følgende sammenligning skal tages med
store forbehold, men jeg tænker på det som "noget i retning af":

-----

I C++ kan jeg:

I 7 ud af 10 tilfælde løse problemet med locals uden at skulle
tænke nævneværdigt over det.

I 2 ud af 10 tilfælde løse det med locals, men må til at tænke
mig om, og evt. indrette designet efter det.

I 1 ud af 10 tilfælde kan jeg ikke løse problemet med locals, selvom
jeg står på hovedet (f.eks. sletning af element fra linket liste),
men er nød til at bruge delete (i det konkrete eksempel med
linket liste kan jeg dog i stedet bruge STL)

-----

I Java:

Har jeg i 9 ud af 10 tilfælde overhovedet ikke noget problem (kun
lager resource)

I 1 ud af 10 tilfælde skal jeg bruge "close-idiomet"

-----

Hvordan man vurderer tingene afhænger naturligvis af forholdstallene.

Min vurdering bygger på to observationer:

De 9/10 i Java slår de 7/10+2/10 i C++, og den sidste 1/10 går
lige op.

Men ... og det er værd at bemærke, de 9/10 i Java er alle lagerplads,
og grupperne er derfor ikke sammenfaldende mht. de problemer de
løser. _Derfor_ er C++ ofte mere bekvem når det drejer sig om at
løse problemet i forbindelse med andet end lagerplads (nemlig indenfor
de 7/10 i C++), men C++ er altid (i det mindste lidt) ringere når det
drejer sig om objekter der kun råder over én resource, nemlig
lagerplads, og disse objekter er i meget stort overtal.

>Altså må C++ for den erfarne programmør være mere sikkert, fordi programmøren
>_ved_ hvordan man programmerer moderne C++, og der ved kan sikre at _alle_
>resourcer bliver frigivet?

Jeg tror det er meget svært at vurdere hvad der vil være "bedst" for
den erfarne programmør - de to ting vil nok komme ud rimelig lige.
Også i Java kan man generelt løse nogle af problemerne ved at vælte
dem over på designet, men det er jeg som bekendt ikke så begejstret
for.

Til gengæld er jeg ikke et øjeblik i tvivl om hvad der vil være bedst
for den _uerfarne_ programmør!

>Problemet med manglende håndtering til nedlæggelse af resourcer i java er vel i og
>for sig _præcis_ det samme som "problemet" med new/delete i C++?

Ja, delete er en slags "close" for et objekt (ved at den aktiverer
destructoren, der indeholder "close"-funktionaliteten). Forskellen er
bare at _alle_ objekter bruger lagerplads, og det at jeg kan se at min
memory stille og rolig forsvinder, giver mig _ingen_ indikation af
hvor i mit program det er galt. Med andre resourcer er det lettere,
fordi de kun anvendes i et mere begrænset omfang, og det bliver
derfor lettere at lokalisere problemet når det først er konstateret.
Hvis jeg skal vælge, vil jeg hellere skulle finde en leak, der _ikke_
er en memory leak.


/Flemming Jensen


Jonas Meyer Rasmusse~ (03-04-2002)
Kommentar
Fra : Jonas Meyer Rasmusse~


Dato : 03-04-02 20:47

"Flemming Jensen" <nospam@nospam.com> wrote in message
news:3cab2d8a.12491712@news.cybercity.dk...
> Til gengæld er jeg ikke et øjeblik i tvivl om hvad der vil være bedst
> for den _uerfarne_ programmør!
Ja, ML ;)


> >Problemet med manglende håndtering til nedlæggelse af resourcer i java er
vel i og
> >for sig _præcis_ det samme som "problemet" med new/delete i C++?
>
> Ja, delete er en slags "close" for et objekt (ved at den aktiverer
> destructoren, der indeholder "close"-funktionaliteten). Forskellen er
> bare at _alle_ objekter bruger lagerplads, og det at jeg kan se at min
> memory stille og rolig forsvinder, giver mig _ingen_ indikation af
> hvor i mit program det er galt.

Det har man jo værktøjer til at vise.. Jeres allesammen's favorit-fjende #1,
har et
værktøj der følger med deres compiler/debugger, der kan hjælpe en til den
slags.

.... og.. hvis man nu lige kun allokerer hukommelse i 1 ud af 10 gange, så
sker det vel så sjældent at det er nemmere at lokalisere.

> Med andre resourcer er det lettere,
> fordi de kun anvendes i et mere begrænset omfang, og det bliver
> derfor lettere at lokalisere problemet når det først er konstateret.
> Hvis jeg skal vælge, vil jeg hellere skulle finde en leak, der _ikke_
> er en memory leak.

... Tak for dit svar, jeg tror vi er enige

mvh JOnas



Thorbjørn Ravn Ander~ (25-03-2002)
Kommentar
Fra : Thorbjørn Ravn Ander~


Dato : 25-03-02 10:04

Martin Ehmsen <ehmsen@imada.sdu.dk> writes:

> anledning til undren over hvorfor klasser i Java ikke kan have
> destructors som de kendes fra C++.

Du har ingen garanti for hvornaar et objekt bliver nedlagt (det er
fidusen ved automatisk oprydning), og selvom der er en
"finalize"(etellerandet) metode du kan implementere, er du ikke
garanteret at den naar at blive kaldt inden JVM'en afsluttes.

Der er en hel del om det paa nettet.
--
Thorbjørn Ravn Andersen
http://homepage.mac.com/ravn

Martin Mouritzen (26-03-2002)
Kommentar
Fra : Martin Mouritzen


Dato : 26-03-02 01:59

After I finished the 3 Pan Galactic Gargle Blasters,
thunderbear@bigfoot.com (Thorbjørn Ravn Andersen) just offered me, he
muttered some weird stuff, and I had to correct this gibberish:

>og selvom der er en
>"finalize"(etellerandet) metode du kan implementere, er du ikke
>garanteret at den naar at blive kaldt inden JVM'en afsluttes.

Faktisk garanteres du ikke at JVM'en kalder den overhovedet.
--
Nano Martin Mouritzen Phone +45 24899896
Vestergade 43 Programmer Advanced Simplicty
DK-8000 Århus martin@nano.dk http://www.nano.dk
Note: Nano søger samarbejdspartnere, se mere på websitet

Søg
Reklame
Statistik
Spørgsmål : 177558
Tips : 31968
Nyheder : 719565
Indlæg : 6408926
Brugere : 218888

Månedens bedste
Årets bedste
Sidste års bedste