2015-06-07 29 views
10

Uwaga na użycie polecenia Exit w funkcjach inline! Używam tutaj Delphi XE3.Czy to błąd, który próbuje skompilować ten kod powoduje zakończenie pracy IDE lub nie działa kompilator?

Objaw

W pewnych okolicznościach, kiedy wykonywane jest połączenie do funkcji inline, który zawiera polecenie Exit i wartość powrót funkcji inline służy bezpośrednio w WriteLn(), kompilator zgłasza błąd wiadomość,

"dcc" exited with code 1.

lub nawet najgorsze, IDE Delphi kończy się bez potwierdzenia.

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. 

Jeśli jednak wartość powrotu funkcji liniowego jest przechowywany w zmiennej, a następnie jest wykorzystywana w WriteLn() problem nie występuje.

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

Pytania

  1. Jest to błąd kompilatora?
  2. Jeśli to błąd, czy istnieje sposób na bezpieczne wyjście z funkcji wstawiania?
+0

To sprawia, że ​​zastanawiam się, czy można się spodziewać tego, aby wyjść z kontekstu dzwoniącego, czy tylko funkcję inline? – TLama

+0

@ TLama Myślę, że pytający wie, że 'inline' nie zmienia znaczenia' exit'.To wewnętrzny AV, który zabija IDE, to jest problem. –

Odpowiedz

10

To z pewnością błąd. Występuje we wszystkich testowanych przeze mnie wersjach IDE, XE3, XE7 i XE8. Szczerze mówiąc, nie sądzę, że można zrobić wiele. Dla mnie IDE kończy się kompilacją za każdym razem. Myślę, że będziesz musiał napisać kod w sposób, który nie doprowadzi do awarii IDE.

Możesz użyć opcji IDE, która zmusza kompilację do użycia msbuild. W ten sposób kompilacja jest oddzielnym procesem, co gwarantuje, że środowisko IDE nie ulegnie awarii. Nic ci to jednak nie pomoże, ponieważ chociaż twoje IDE nie umrze, nadal nie będziesz w stanie skompilować swojego programu!

Kiedy budować z msbuild, masz błąd w tej formie:

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

GPF stoi General Protection Fault, że jest to naruszenie dostępu do pamięci. Prawdopodobnie jest to nieobsługiwany wyjątek, który zabija IDE podczas wykonywania kompilacji.

Moja rada jest taka, że ​​przesyłasz zgłoszenie błędu do Quality Portal. Jest to jedyny sposób na naprawienie defektu. Chociaż nie oczekuj, że kiedykolwiek dojdzie do rozwiązania problemu XE3.

+0

Heffernan, dzięki za odpowiedź. Przesłałem [błąd] (https://quality.embarcadero.com/browse/AP-165) do portalu jakości. Myślę, że jestem zmuszony użyć 'goto' * labelExit * jako obejścia na teraz. – Astaroth

+0

@Astaroth - wychodzenie nie zawsze jest problemem. Wydaje się, że jest to w porządku f.i: Wynik: = iNumber <> 0; jeśli nie Wynik, a następnie Wyjdź; ... –

2

Jednym z obejść, którego można użyć tutaj, jest odwrócenie warunkowej implementacji, a tym samym unikanie użycia polecenia Zakończ.

Więc zamiast korzystania

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

użycie

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, Doceniam twój komentarz, więc daj mi +1. Jednak w moim przykładzie pokazuję, że polecenie 'Exit' zachowuje się nieoczekiwanie w pewnych okolicznościach. Mój przykład nie odzwierciedla mojej faktycznej struktury kodu. Jestem pewien, że każdy programista kiedykolwiek spotkał się z sytuacją, w której 'Wyjście' bezpośrednio z funkcji jest najlepszą dostępną opcją pod względem wydajności. W każdym razie, zgadzam się z tobą, że czasami (jak w moim przykładzie) unikanie polecenia 'Exit' nie zmniejsza wydajności kodu. – Astaroth

+0

Podejrzewałem, że rozwiązanie nie może być takie proste, ale nadal nie uwierzysz, ile razy możesz przeoczyć nawet najprostsze rozwiązania. Zwłaszcza, gdy poświęcasz trochę czasu na rozwodzenie się nad rozwiązywaniem jakiegoś problemu i zapominanie, aby pójść i spojrzeć na cały obraz, a przede wszystkim spróbować uniknąć tego problemu. – SilverWarior

+0

@Silver Prawdziwy kod jest prawdopodobnie większy i uniknięcie wyjścia sprawiłoby, że funkcja byłaaby mniej wyraźna. –