2015-06-07 6 views
10

Attenzione all'utilizzo del comando Exit nelle funzioni inline! Ho usato Delphi XE3 qui.Si tratta di un bug che tenta di compilare questo codice, causando la chiusura di IDE o il mancato avvio del compilatore?

sintomo

In alcuni casi, quando viene effettuata una chiamata ad una funzione inline che contiene Exit comando e valore il ritorno della funzione linea viene utilizzata direttamente in WriteLn(), il compilatore segnala un errore messaggio,

"dcc" exited with code 1.

o, peggio ancora, l'IDE Delphi termina senza alcuna conferma.

function ProcessNumber(const iNumber: Integer): Boolean; inline; 
begin 
    if iNumber = 0 then begin 
    Result := False; 
    Exit; 
    end; 
    // some code here ... 
    Result := True; 
end; 

procedure Test; 
begin 
    writeln(ProcessNumber(0)); 
end; 

begin 
    Test; 
    ReadLn; 
end. 

Tuttavia, se il valore restituito della funzione inline è memorizzato in una variabile, e quindi la variabile è utilizzata nel WriteLn(), il problema non si verifica.

procedure Test; 
var 
    b: Boolean; 
begin 
    b := ProcessNumber(0); 
    writeln(b); 
end; 

Domande

  1. Si tratta di un bug del compilatore?
  2. Se si tratta di un errore, esiste una soluzione alternativa per uscire in modo sicuro da una funzione in linea?
+0

E mi domando, cosa si aspetta questo per uscire dal contesto del chiamante, o semplicemente la funzione inline? – TLama

+0

@TLama Penso che chi lo sa sappia che 'inline' non cambia cosa significhi' exit'.È l'AV interno che uccide l'IDE che è il problema. –

risposta

10

Questo è sicuramente un bug. Si verifica in tutte le versioni IDE che ho testato, XE3, XE7 e XE8. Onestamente non penso che ci sia molto da fare. Per me l'IDE termina con la compilazione ogni volta. Penso che dovrai solo scrivere il codice in un modo che non porti a crash di IDE.

È possibile utilizzare l'opzione IDE che forza la compilazione a utilizzare msbuild. Ciò colloca la compilazione in un processo separato e assicura che l'IDE non si arresti in modo anomalo. Non ti aiuterà molto perché, anche se il tuo IDE non continuerà a morire, non sarai ancora in grado di compilare il tuo programma!

Quando si compila con msbuild, si ottiene un errore di questo modulo:

error F2084: Internal Error: GPFC00000FD-004D3F34-0

Il GPF acronimo di protezione generale, che è una violazione di accesso di memoria. Questa è presumibilmente un'eccezione non gestita che sta uccidendo l'IDE quando la compilazione viene eseguita in corso.

Il mio consiglio è di inviare una segnalazione di bug a Quality Portal. Questo è l'unico modo per correggere il difetto. Sebbene non si aspetti che una correzione venga mai a XE3.

+0

Heffernan, grazie per la risposta. Ho inviato [il bug] (https://quality.embarcadero.com/browse/AP-165) al portale di qualità. Penso che, per ora, sono costretto a usare 'goto' * labelExit * come soluzione temporanea. – Astaroth

+0

@Astaroth - l'uscita non è sempre un problema. Questo sembra perfetto f.i: Result: = iNumber <> 0; se non Risultato, esci; ... –

2

Una soluzione alternativa che è possibile utilizzare qui è di invertire l'implementazione condizionale if e quindi evitare del tutto l'utilizzo del comando Exit.

Così, invece di utilizzare

function ProcessNumber(const iNumber: Integer): Boolean; inline; 
begin 
    if iNumber = 0 then begin 
    Result := False; 
    Exit; 
    end; 
    // some code here ... 
    Result := True; 
end; 

uso

function ProcessNumber(const iNumber: Integer): Boolean; inline; 
begin 
    if iNumber <> 0 then begin 
    // some code here 
    Result := True; 
    end; 
    else 
    Result := False; 
    //No exit needed here as this is already at the end of your method 
end; 
+1

SilverWarior, apprezzo il tuo commento, quindi +1 da me. Tuttavia, nel mio esempio, mostro solo che risulta che il comando "Exit" si comporta in modo imprevisto in determinate circostanze. Il mio esempio non riflette la mia vera struttura del codice. Sono sicuro che ogni sviluppatore ha mai affrontato una situazione in cui "Exit" immediatamente da una funzione è la migliore opzione disponibile in termini di efficienza. Ad ogni modo, sono d'accordo con te che a volte (come nel mio esempio) evitare il comando "Esci" non riduce le prestazioni del codice. – Astaroth

+0

Sospettavo che la soluzione non potesse essere così semplice, ma non crederesti mai quante volte potresti trascurare anche le soluzioni più semplici. Soprattutto quando passi un po 'di tempo a sbattere la testa sulla risoluzione di qualche problema e dimenticando di andare a vedere il quadro generale e cercare di evitare il problema in primo luogo. – SilverWarior

+0

@Silver Il codice reale è probabilmente più grande ed evitando l'uscita renderebbe la funzione meno chiara. –

Problemi correlati