Mogens Hansen skrev:
> Jeg tror ikke at koden gør det som du tror.
> Du allokerer _en_ char på heapen, som bliver initialiseret med værdien x.
> Jeg antager at du ønskede at allokere et array af char, med en længde på
> x+1.
> Idet jeg foretrækker at erklære og initialisere variable samtidig, hvis
det
> er muligt, bliver det til
> char* str = new char[x+1];
Ja, det er rigtigt. Jeg var åbenbart lidt for hurtig til at skrive beskeden.
Ved du hvad 'new char(x+1)' allokerer? - for det virker tilsyneladende også
(jeg tester altid hurtigt mine programmer, før jeg sender koden) - selvom
det jo er char[x+1] der er det rigtige.
> > // Selvfølgelig burde man også checke at x!=0 og
> > str ikke bliver sat til NULL
>
> Nej, man må gerne skrive "new char[0]", og det giver _ikke_ 0 tilbage. Den
> situation vil du dog ikke komme i, idet du altid allokerer "x+1". Man må
> naturligvis ikke tilgå hukommelse ud over hvad man har allokeret.
>
> Nej, man behøves ikke at checke om str bliver sat til 0 - det gør den
> _ikke_.
> Såfremt new ikke kan allokere den ønskede hukommelse, bliver der smidt en
> exception.
"If there is insufficient memory for the allocation request, by default
operator new returns NULL. You can change this default behavior by writing a
custom exception-handling routine and calling the _set_new_handler run-time
library function with your function name as its argument. For more details
on this recovery scheme, see The operator new Function." -- under 'new
Operator' i MSDN Library.
Hvis jeg ikke, som der står, har skrevet min egen fejlroutine og kaldt
_set_new_handler, vil new returnere NULL når der ikke er nok plads - eller
har jeg fejlfortolket det?
Måske du evt. kunne fortæller hvordan en sådan routine laves, så jeg kan
bruge det i stedet? Det er jo mere 'højniveau'sk'.
> [snip]
> > str[0] = '<';
> > str[x-1] = '>';
> > str[x] = '\0';
> > return str;
>
> Her skal du naturligvis tage hensyn til størrelsen på x, sådan som du
> egentlig også siger man burde.
Det var rent faktisk også i den henseende at jeg skrev det.
> Her skriver du i ikke allokeret hukommelse, fordi det ikke er et array du
> har allokeret, som nævnt ovenfor.
> Jeg kan varmt anbefale at bruge værktøjer, såsom CodeGuard som er en del
af
> Borland C++Builder Professional og Enterprise, til at hjælpe med at finde
> den slags fejl. Der findes flere andre værktøjer, der har samme formål.
Hvad med i Microsoft Visual C++ 6.0?
> > } // Tag jer ikke af at funktionen egentlig ikke kan bruges til noget
> > fornuftigt!
> >
> > int main(int argc, char *argv[])
> > {
> > cout << funktion(10) << endl;
> > return 0; // Bliver strengen jeg oprettede i 'funktion' nu frigjort
> fra
> > rammen?
>
> Ikke nødvendigvis.
> Selv hvis man befinder sig i omgivelser, der frigiver hukommelse efter
> programmet er termineret, mener jeg det er en dårlig vane at basere sig på
> det.
Jeg vil selvfølgelig selv frigøre rammen - udover at det medfører
midlertidig pladsspild, kan det også være forvirrende ikke at kunne se hvor
den bliver frigjort.
> Det gør det langt sværere at anvende værktøjer, der hjælper med at finde
> leaks.
> Tænk også på det som resourcer generelt: file-handles, database
> transaktioner, netværks forbindelser. Database resourcer er specielt
> interessante, fordi man kan have allokeret resourcer i en anden proces.
>
> Det er ikke vanskelligt at undgå.
> I dit eksempel kunne man have brugt klassen std::string:
>
> std::string funktion(unsigned x)
> {
> std::string result(x, '-');
> if(x > 0)
> result[0] = '<';
> if(x > 2)
> result[x-1] = '>';
> return result;
> }
>
> int main(void)
> {
> std::cout << funktion(10) << std::endl; // No problem
> }
>
> Det er enklere, klarere, sikrere og giver _ingen_ _mulighed_ for
> memory-leak.
> Det behøver end ikke at være langsommere.
Så ved jeg det - det jeg ikke vidste i forvejen. Tak for svaret.
Mvh. Bjarke