2016-09-02 7 views
4
내가 그것을 라인 1에 경고를 제공하는 아래의 코드를 컴파일

경우 '초기화되지 않은 변수'에 대한 변경 사항 : *'사용되지 않는 값'

그러나 경우에 사용한 적이 lTime에 할당

값을 나는 2 행에 다른 경고를, 그 줄을 제거 :

lTime가 초기화되지 않았 변수

컴파일러에 누락 된 항목이 있습니까? 그렇지 않습니까? 나뿐만 아니라 예외 lTime를 할당하기 때문에

procedure TFormWebServices.RemoveOldReports; 
var 
    TSR  : TSearchRec; 
    I   : Integer; 
    lCutOff, 
    lTime  : Int64; 
    TSToDelete: TStringList; 
    S,Msg  : String; 
    E   : Exception; 
begin 
    lCutOff := DelphiToJavaDateTime(Now - cDefReportLifeMins/1440); 
    I := FindFirst(FReportDir + '*.pdf',0,TSR); 
    TSToDelete := TStringList.Create; 
    while I = 0 do 
    begin 
    if (TSR.Attr and faDirectory) = 0 then 
    begin 
     lTime := lCutOff;   // Line 1 
     try 
     lTime := StrToInt64(Copy(TSR.Name,1,pos('.',TSR.Name)-1)); 
     except 
     on E:Exception do lTime := lCutOff; 
     end; 
     if lTime < lCutOff then // Line 2 
     TSToDelete.Add(TSR.Name); 
    end; 
    I := FindNext(TSR); 
    end; 

이, Why is the Compiler warning that variable may not be initialized?의 속는 사람이 아니다.

+1

가능한 중복 (HTTP : // 유래. com/questions/11554857/why-is-the-compiler-warning-that-variable-may-be-initialized) –

+1

실제로 중복 된 것처럼 보입니다. –

+0

그래도 여기에서는 예외 처리를 사용할 필요가 없습니다. RTL은 정확하게이 목적을위한'TryStrTo [x]'메소드를 제공합니다. 예외 처리기가 처리하는 것보다 훨씬 효율적입니다. [TryStrToInt64 Documentation] (http://docwiki.embarcadero.com/Libraries/en/System.SysUtils.TryStrToInt64) –

답변

7
lTime := lCutOff;  
try 
    lTime := StrToInt64(Copy(TSR.Name,1,pos('.',TSR.Name)-1)); 
except 
    on E:Exception do lTime := lCutOff; 
end; 
if lTime < lCutOff then 
    TSToDelete.Add(TSR.Name); 
을 할 수

컴파일러는이 코드에 대해 경고합니다. 첫 번째 줄에 lTime := lCutOff을 할당하면 해당 할당에 쓰여진 값은 읽히지 않습니다.

그러나 코드를 제거 할 때 코드가 잘리지 않는 경우가 있습니다.

try 
    lTime := StrToInt64(Copy(TSR.Name,1,pos('.',TSR.Name)-1)); 
except 
    on E:Exception do lTime := lCutOff; 
end; 
if lTime < lCutOff then 
    TSToDelete.Add(TSR.Name); 

고려해야 할 두 가지 시나리오가 있습니다 예외는 try/except 블록 내에서 발생하지 않습니다, 또는 예외가가 발생합니다.

예외가 발생하지 않으면 lTimeStrToInt64이라는 결과가 할당되므로 읽기 전에 초기화됩니다.

예외가 발생하면 lTime이 블록 내부에서 초기화되지 않습니다. 다음에 어떻게 될까요?

  • 예외 Exception (강제하지 않음)로부터 도출하면 다음 붙잡아서 lTime 초기화된다.
  • 예외가 Exception에서 파생되지 않으면 catch되지 않고 lTime을 읽지 않습니다.

따라서 컴파일러는이 모든 것을 유추 할 수 있으므로 초기화되지 않은 변수 경고를 발행하지 않을 수 있습니다. 그러나 컴파일러는 슬프게도 이러한 복잡성에 대한 플로우 분석을 수행하지 않습니다.나는 그것의 논리는 다음과 같이 실행 있다고 생각 : 예외가 lTime 전에 발생

  1. 초기화

    다음
  2. 예외는 변수 lTime 다음 읽을 경우
  3. 에 잡힐 수 있고, 여전히 수도 초기화되지 않아야한다.

2 단계에서 lTime이 초기화된다는 것을 깨달을 수 있어야하지만 단순히 분석을 수행하지 않아야합니다. 따라서 컴파일러가 더 잘할 수 있다고 주장 할 수는 있지만 분석 알고리즘의 한계로 받아 들여야합니다.

우리는 코드를 작성하고 경고를 피하는 방법을 찾는 작업을해야한다는 것을 알고 있습니다. 우리는 경고를 억제하고 싶지 않습니다. 코드가 정확하고 경고가 없도록 코드를 작성하는 방법을 찾아야합니다.

내 생각에 앞으로의 방법은 예외가 여기에서 사용하는 잘못된 도구라는 것을 인식하는 것입니다. 이 변환에 실패하는 것은 정상적인 동작입니다. 실패 할 경우 예외를 발생시키지 않는 변환 함수를 사용하여 코드를 작성해야합니다. 예를 들어 다음 옵션 중 하나를 사용할 수 있습니다

if TryStrToInt64(..., lTime) then 
    if lTime < lCutOff then 
    .... 
else 
    lTime := lCutoff; 

또는 [? 그 변수를 경고 컴파일러가 초기화되지 않을 수 있습니다 왜]의

lTime := StrToInt64Def(..., lCutoff); 
if lTime < lCutOff then 
    .... 
+1

Delphi XE 컴파일러는이 코드에서 '변수'가 초기화되지 않았을 수 있다는 잘못된 경고를 생성하지 않습니다. – kludg

-1

이것은 올바른 동작입니다. try/except에서는 이전 값을 사용하지 않고 새 값을 지정하므로 경고문을 사용하므로 줄 1 값은 사용되지 않습니다.

실제로 lTime

procedure TFormWebServices.RemoveOldReports; 
var 
    TSR  : TSearchRec; 
    I   : Integer; 
    lCutOff, 
    lTime  : Int64; 
    TSToDelete: TStringList; 
    S,Msg  : String; 
    E   : Exception; 
    begin 
    lCutOff := DelphiToJavaDateTime(Now - cDefReportLifeMins/1440); 
    I := FindFirst(FReportDir + '*.pdf',0,TSR); 
    TSToDelete := TStringList.Create; 
    while I = 0 do 
     begin 
     if (TSR.Attr and faDirectory) = 0 then 
      begin 
       lTime := lCutOff;   // Line 1 
       try 
        lTime :=  StrToInt64(Copy(TSR.Name,1,pos('.',TSR.Name)-1)); 
       except 
        on E:Exception do lTime := lCutOff; 
       end; 
       if lTime < lCutOff then // Line 2 
        TSToDelete.Add(TSR.Name); 
      end; 
     I := FindNext(TSR); 
     end; 

을 값을 설정하지 않고 실패 할 수 있습니다 블록을 제외하고 당신이 시도 외부 lTime 변수를 사용하려고 줄을/제거하면이

procedure TFormWebServices.RemoveOldReports; 
var 
    TSR  : TSearchRec; 
    I   : Integer; 
    lCutOff, 
    lTime  : Int64; 
    TSToDelete: TStringList; 
    S,Msg  : String; 
    E   : Exception; 
    begin 
    lCutOff := DelphiToJavaDateTime(Now - cDefReportLifeMins/1440); 
    I := FindFirst(FReportDir + '*.pdf',0,TSR); 
    TSToDelete := TStringList.Create; 
    while I = 0 do 
     begin 
     if (TSR.Attr and faDirectory) = 0 then 
      begin 
       lTime := StrToInt64Def(Copy(TSR.Name,1,pos('.',TSR.Name)-1), lCutOff); 
       if lTime < lCutOff then  
        TSToDelete.Add(TSR.Name); 
      end; 
     I := FindNext(TSR); 
     end; 
+0

감사합니다. StrToInt ** ** ** ** –

+0

2 번 문항에 동의하지 않았습니다. 행 1이 제거되고 초기화되기 전에 'lTime'을 읽을 수있는 상황은 실제로 없습니다. –

+0

줄 2 경고는 줄 1이 제거 된 경우에만 발생합니다. 왜 그게 잘못입니까? –