Sign in Join
Wiki copytemporary

Revision 2 of 5, by WikiArchive on 11-4-2026. The page as it is now.

Avoiding implicit try finally section/fi

Contents

Epäsuoran try finally lohkon välttäminen

Yleistä

Koodin optimoinnissa se auttaa ymmärtämään, että kääntäjä käärii tiettyjä koodirakenteita epäsuorasti try … finally-lohkoon. Tämä on tarpeen aina, kun käytetään sellaisia muuttujia, kuten ansiString, variants tai dynaamisia taulukoita jotka edellyttävät initialization ja finalization (esim. kun standardi aliohjelmat initialize ja finalize tarvitaan oikean muistin allokoinnin ja hankitun muistin vapauttamiseksi).

Tällöin kääntäjä varmistaa, että msg: n viitenumero lasketaan asianmukaisesti, kun menettely doSomething poistuu poikkeuksella. Usein tämä voi kuitenkin aiheuttaa merkittäviä haitallisia vaikutuksia tuotetun koodin nopeuteen.

Tämä oli ongelma, joka oli fpc-devel -sähköpostilistan aiheketjussa http://www.mail-archive.com/fpc-devel@lists.freepascal.org/msg01367.html TList slowness classes .

Huomaa, että väliaikaiset ansiString-muuttujat voidaan luoda epäsuorasti. Ainoa tapa olla täysin varma siitä, mitä todellisuudessa tehdään, on lukea assemblerin ulostulo.

Mahdolliset ratkaisut

riskejä ja milloin niitä sovelletaan

Warning-icon.png

Warning: Nämä poikkeuskehykset luodaan syystä. Jos niistä jätetään poikkeus niin koodiin jään muistivuoto mahdollisuus

Vuonna 2007 {$implicitExceptions} lisättiin strutils-käännösyksikköön. Jota sysutils on luultavasti seurannut. Tätä varten noudatettiin seuraavaa lähestymistapaa:

Jos havaitset näitä muutoksia, ota yhteyttä Marcoviin.

Demo-ohjelma

Alla on pieni demo-ohjelma

Sen suorittaessaan osoittaa selvästi, että epäsuoran try … finally välttäminen mhdollistaa koodin suorittamisen paljon nopeammin. Kun suoritin tämän ohjelman järjestelmässäni, sain tuloksen:

pascal
time of fooNormal: 141
    time of fooFaster: 17

Variant-tyyppiä/ jotakin muuta tyyppiä joka kerta kun aliohjelmaa kutsutaan mutta vain jos jollakin parametrilla on tietty arvo).

pascal
1program implicitExceptionDemo(input, output, stderr);
     2
     3// for exceptions
     4{$mode objfpc}
     5// data type 'string' refers to 'ansistring'
     6{$longstrings on}
     7
     8uses
     9  {$IFDEF UNIX}
    10    // baseUnix, unix needed only to implement clock
    11    BaseUnix, Unix,
    12  {$ENDIF}
    13    sysUtils;
    14
    15function clock(): int64;
    16
    17var
    18  {$IFDEF UNIX}
    19    dummy: tms;
    20  {$ELSE}
    21    TS : TTimeStamp;
    22  {$ENDIF}
    23begin
    24  {$IFDEF UNIX}
    25	clock := fpTimes(dummy);
    26  {$ELSE}
    27   TS:=DateTimeToTimeStamp(Now);
    28   result := TS.Time;
    29  {$ENDIF}
    30end;
    31
    32
    33
    34// Note: when fooNormal and fooFaster are called
    35//       i is always >= 0, so no exception is ever actually raised.
    36// So string constants SNormal and SResString are not really used.
    37
    38procedure fooNormal(i: integer);
    39var
    40	s: string;
    41begin
    42	if i = -1 then
    43	begin
    44		s := 'Some operation with AnsiString';
    45		raise exception.create(s);
    46	end;
    47end;
    48
    49procedure fooFaster(i: integer);
    50	procedure raiseError;
    51	var
    52		s: string;
    53	begin
    54		s := 'Some operation with AnsiString';
    55		raise exception.create(s);
    56	end;
    57begin
    58	if i = -1 then
    59	begin
    60		raiseError;
    61	end;
    62end;
    63
    64
    65// M A I N =================================================
    66const
    67	testCount = 10000000;
    68var
    69	i: integer;
    70	start: int64;
    71begin
    72	start := clock();
    73	for i := 0 to testCount do
    74	begin
    75		fooNormal(i);
    76	end;
    77	writeLn('time of fooNormal: ', clock() - start);
    78	
    79	start := clock();
    80	for i := 0 to testCount do
    81	begin
    82		fooFaster(i);
    83	end;
    84	writeLn('time of fooFaster: ', clock() - start);
    85end.

Laittamalla raiseError toiseen näkyvyyteen fooFaster aliohjelmassa, keskeysten käsittely ei tule osaksi pääkäyttöistä suoritusosaa.


From the Free Pascal wiki, page "Avoiding implicit try finally section/fi", as the Internet Archive kept it on 2022-08-13. Copyright stays with the author who wrote it, according to the old wiki's Licensing page. If you have concerns about this material, message the admin.