Pytanie Ostrzeżenie "ostrzeżenie kompilatora może być niezdefiniowane"


Często używam kodu zgodnego z:

function GetNumber(Handle : THandle) : Integer;
begin
FLock.BeginRead;
try
  if FMap.TryGetValue(Handle, Object) then
    raise EArgumentException.Create('Invalid handle');
  Result := Object.Number;
finally
  FLock.EndRead;
end;
end;

Niestety kompilator daje mi ostrzeżenie dla wszystkich tych metod:

[DCC Warning] Unit.pas(1012): W1035 Return value of function 'GetNumber' might be undefined

Znam to ostrzeżenie, ale w tym przypadku nie widzę żadnego powodu. A może scenariusz, którego mi brakuje, spowodowałby niezdefiniowaną wartość wyniku? Rozumiem ostrzeżenie w przypadku try..except ale dla try..finally to nie ma dla mnie sensu.

Pytania:

  • Czy jest jakikolwiek powód ostrzeżenia?
  • Jak mogę się tego pozbyć (przenoszenie Result := Object.Number wyjście z zamka nie jest opcją i chcę uniknąć pisania zupełnie niepotrzebnego Result := 0 linia na górze każdej funkcji)

Dzięki!


12
2017-07-04 10:29


pochodzenie


+1. Niestety musiałem sobie z tym poradzić kilka razy. Znajdziesz trochę Result := X; // Avoid compiler warning w moim kodzie niektóre z nich zostały kompilowane warunkowo z powodu zmian kompilatora między wersjami. Embarcadero powinien naprawić ten błąd, ponieważ jest denerwujący! - Cosmin Prund


Odpowiedzi:


Czy jest jakikolwiek powód ostrzeżenia?

Nie widzę jednego, ale jest tam ze względu na raise

Jak się go pozbyć (przesuwając wynik Result = linia Object.Name   zamek nie jest opcją i chcę   aby uniknąć pisania całkowicie   niepotrzebny Wynik: = 0 linii u góry   każdej funkcji)

Przenieś instrukcję podniesienia do własnej procedury.

function GetNumber(Handle : THandle) : Integer;
    procedure InvHandle;
    begin
        raise EArgumentException.Create('Invalid handle');
    end;
begin
    FLock.BeginRead;
    try
        if FMap.TryGetValue(Handle, Object) then
            InvHandle;
        Result := Object.Number;
    finally
        FLock.EndRead;
    end;
end;

5
2017-07-04 10:45



To naprawdę nie jest problem z podbiciem. Kompilator już dawno zauważył, że ścieżka kodowa z podbiciem zwalnia kodera z obowiązku przypisania do wartości zwracanej. Spróbuj skompilować kod OP, ale z Try / Finally usunięty! - David Heffernan
@David - Nie ma ostrzeżenia kompilatora bez próby. Ale nie sądzę, jest to dobre rozwiązanie problemu pod ręką, aby usunąć blok try..finally. Przeniesienie instrukcji raise również usuwa ostrzeżenie, więc domyślam się, że błąd w kompilatorze ma związek z użyciem podniecenia w bloku try..finally. - Mikael Eriksson
@Mickael Nie sugeruję, że rozwiązaniem jest usunięcie try/finally!!! Chodzi mi o to, że jest to wyraźnie błąd kompilatora. - David Heffernan
@David - Jak możesz być pewien, że to jest problem try/finallyale nie z raise? Usunięcie któregoś z nich rozwiązuje ostrzeżenie ?! - Lieven Keersmaekers
@craig nie przeczytałeś powyższych komentarzy? - David Heffernan


To jest błąd kompilatora. Jeśli try/finally jest usuwany, a ostrzeżenie nie jest emitowane. Kompilator od dawna był w stanie rozpoznać, że raise zwalnia kodera z obowiązku przypisania wartości zwracanej. Z jakiegokolwiek powodu try/finally wydaje się mylić jego analizę.


Być może nie jest to błąd kompilatora. Co jeśli kod w finally blok przestał propagować wyjątek? Najwyraźniej nie ma except obsługi, ale raczej podejrzewam, że jedna z procedur obsługi wyjątków w System lub SysUtils jednostka może być w stanie zatrzymać postępujący wyjątek.


3
2017-07-04 10:48



"ale raczej podejrzewam, że jedna z procedur obsługi wyjątków w jednostce System lub SysUtils może być w stanie zatrzymać wyjątek postępujący dalej" Co sprawia, że ​​tak myślisz? I dlaczego mieliby to robić? - jpfollenius
@Smasher Nie jestem teraz taki pewien. myślałem AcquireExceptionObject przerwałby wyjątek, ale nie sądzę. - David Heffernan
Jeśli nie było raise oświadczenie, ale po prostu try …; Result := …; finally … end;, nie byłoby żadnego niezdefiniowanego ostrzeżenia o wartości zwracanej, nawet jeśli wyjątek byłby możliwy przed uzyskaniem instrukcji przypisania wyników. - Andriy M
Usuwanie try/finally usuwa ochronę zasobów blokady! Pierwszy wyjątek, i nigdy nie odblokujesz. Również, jeśli w końcu uda się zablokować / zatrzymać wyjątek popagający - istnieje znacznie poważniejszy problem! - Craig Young
@Craig Obawiam się, że całkowicie źle zrozumiałeś nacisk mojego postu i zmarnowałeś swój cenny downward. Oczywiście nie jestem zwolennikiem tego, że OP usuwa próbę / w końcu. To byłoby szalone. Punktem, który robię, jest interakcja pomiędzy try / finally a ostrzeżeniem kompilatora. Ostrzeżenie nie jest emitowane, gdy nie ma opcji try / finally, nawet jeśli nie ma wpływu na to, czy została ustawiona wartość zwracana. - David Heffernan


Zadanie

Result := ...;

w finally brak bloku.


-2
2017-07-04 10:33



Nie, nie brakuje. - Cosmin Prund
Dodatkowy wynik jest wymagany dla except blok - nie a finally blok. - Craig Young