2012-03-08 3 views
1

두 listboxes.I 두 개의 목록 상자를로드하는 응용 프로그램에서 작업하고 있습니다 및 목록 상자에서 항목을 클릭하여 유지할 때 디버깅하는 동안 다음 오류가 나타납니다 . EXE 파일을 실행델파이 스택 오버플로 이벤트 처리에서 사이클로 인해

enter image description here

내가 "액세스 위반"메시지가 close.Sometimes에 응용 프로그램을 발생합니다.

그렇다면이 aaplication에서이 오류를 제거하려면 어떻게해야합니까?

EDIT

..

주요 형태는 모든 컨트롤 timer_RefreshCOntrol를 리프레시 타이머를 갖고 (intervali 1).

은 editBox_one가 수정 whenver (값) 이 기능은 내가 원래 개발자 아니다 FormCreate

EDIT2

Procedure TStringSetting.SetValue (const AValue : String); 
    Begin 
    ... 
    If FValueControl <> Nil then 
    Begin 
    FValueControl.OnChange := VoidNotifyEvent; 
    FValueControl.Text := NewValue; 
    FValueControl.OnChange := EditChange;  //<--here the stackoverflow error comes.... 
    end; 
    end; 




Procedure EditChange (Sender: TObject); 
    Begin 
     Value := FValueControl.Text; 
     If Not EditIsValid then FValueControl.Font.Color := clRed 
     else If Dirty then FValueControl.Font.Color := clBlue 
        else FValueControl.Font.Color := clWindowText; 

     If @OldCustomEditChange <> Nil then OldCustomEditChange(Sender); 
    end;` 


    the EditChange (Sender: TObject); <--keeps geting called and the stackoverflow error comes 

EditChange

이 편집 상자에 할당이라고합니다. 난 그냥 때로는 코드를 처리, 주요 리펙토링은 불가능합니다.

편집 3 호출 스택 값은 무엇이지만 "???" 내가 무한 호출이

Procedure TFloatSetting.EditChange (Sender: TObject); 
    Begin 
    SkipNextOnChange := True; 
    Inherited EditChange(Sender); 
    IfValidThenStore(FValueControl.Text); 
    Inherited EditChange(Sender); {<-------This is where it start} 
end; 


Procedure TStringSetting.EditChange (Sender: TObject); 
    Begin 
    Value := FValueControl.Text; 
    If Not EditIsValid then FValueControl.Font.Color := clRed 
    else If Dirty then FValueControl.Font.Color := clBlue 
        else FValueControl.Font.Color := clWindowText; 

    If @OldCustomEditChange <> Nil then OldCustomEditChange(Sender); {<---this keeps calling Procedure TFloatSetting.EditChange (Sender: TObject);} 
end; 
+3

! 물론 Windows 목록 상자는 버그가 없습니다. 특정 코드를 보여줘야합니다. –

+2

우선, 타이머를 사용하십시오 (특히 간격이 1 인 경우 - 초당 천 이겠지만 이는 TTimer로 얻을 수있는 것보다 훨씬 많으며 CPU 시간 낭비). 이것에 대해 끔찍한.아무튼, 대부분 자신이 호출하는 프로 시저 또는 첫 번째 프로 시저를 호출하는 다른 프로 시저가있을 가능성이 큽니다. 쉽게 찾을 수 있어야합니다. 아마도 EditChange가 호출되어 EditChange가 호출되어 EditChange가 호출되고 * ad infinitum *이 호출됩니다. 이것을 확인하려면'삑 '을 추가하십시오. sleep (1000)'을 사용하여 EditChange를 시작합니다. (계속) –

+0

(계속) 나의 가설이 맞다면, 프로그램을 죽일 때까지 잠깐 비프 음을 울려 야한다. –

답변

9

오류가 발생하는 이유는 분명하다 : TStringSetting.EditChangeTFloatSetting.EditChange을 트리거 차례로 그 TStringSetting.EditChange을 트리거합니다. 루프는 스택 공간이 모두 소모 될 때까지 이와 같이 계속됩니다. 여기

디버깅과 문제를 해결하는 방법에 대한 몇 가지 그런 일이 이유에 대한 도움말과 팁은 다음과 같습니다
  • 어쩌면을 트리거 Value가 progrmatically 변경되는 OnChange 이벤트 핸들러와 관련된 제어합니다. 두 편집자가 동일한 데이터를 두 가지 형식으로 표시해야하고 해당 동기화를 유지하기 위해 각각 OnChange 이벤트 핸들러를 사용하는 경우 이것이 원인 일 수 있습니다.
  • 다른 이벤트 핸들러를 직접 호출하는 것일 수 있습니다.

방법이를 디버깅하는 : paulsm4에 의해 제안

  • 은 먼저, 브레이크 포인트 솔루션을 시도해야합니다. OnChange 핸들러 중 하나를 호출 할 때마다 스택 오버플로가 발생하면이 솔루션이 쉽게 작동합니다.
  • 이벤트 핸들러 중 하나에 대한 코드를 주석 처리하십시오. 프로그램을 실행하면 오류가 더 이상 나타나지 않습니다. 작은 (그러나 논리적 인) 양으로 코드를 주석 해제하고, 테스트하고 반복하십시오. 오류가 다시 나타나면 오류의 원인이되는 행에 대한 기금을 확보 한 것입니다. 자신을 알아낼 수없는 경우 질문을 편집하고 코드를 추가 한 다음 방금 발견 한 행에 문제가 발생했음을 표시하십시오. 확실히 무한 재귀 루프를 중지 할 것입니다 : 당신이 OnChange 이벤트 핸들러를 트리거되어 사용하고있는 컨트롤을 프로그래밍 방식으로 변경 될 때이 값 경우

, 당신은 이벤트 핸들러 비 재진입을해야한다. 나는 거의 항상 컨트롤 속성을 코드에서 변경 OnChange 또는 이에 상응하는 이벤트를 트리거하고 항상 같은 것을 사용하여 다시 항목에서 자신을 보호 가정

이 작은 정보를 말할 완전히 불가능
// Somewhere in the private section of your form's class: 
FProcessingEventHandler: Boolean; 

// This goes in your event handler 
procedure TYourForm.EventHandler(Sender:TObject); 
begin 
    if FProcessingEventHandler then Exit; // makes code non-reentrant 
    FProcessingEventHandler := True; 
    try 
    // old code goes here ... 
    finally FProcessingEventHandler := False; 
    end; 
end; 
+0

위의 코드가 작동하고 스택 오버플로 오류가 발생하지 않았으므로 고맙습니다. –

3

을 시작 장소를 가지고 enter image description here

EDIT 4

@Cosmin Prund을 거쳐 및 @ 데이비드 당신은 종료되지 않는 재귀를보고 호출 순서는 EditChange입니다. EditChange에 동일하다면, 또는 차례로 EditChange를 호출하는 함수를 호출

  1. OldCustomEditChange : EditChange의 코드를 보면 두 개의 재귀 호출 후보가있다.
  2. 에 대한 변경 내용에 응답하는 이벤트 처리기는 EditChange을 호출합니다.

EditChange의 코드는 자신을 호출 할 수있는 유일한 기회입니다.

이러한 두 가지 가능성이 비 종결적 인 재귀 함수 호출과 결국 스택 오버플로를 초래하는 것을 쉽게 볼 수 있습니다. 두 후보자 중 내기가 1입니다. OldCustomEditChange이 호출 될 때 어떤 일이 발생하는지 신중하게 연구 할 것입니다.

이 스택 오버플로를 디버깅하려면 호출 스택 창을 열고 긴 호출 순서를 살펴보십시오. 일반적으로 하나 이상의 중간 함수를 통해 하나의 함수가 자신을 호출하는 패턴을 보게됩니다.

3

제안 :

  1. 그들을 호출 누가 볼 EditChange과 OldCustomEditChange에 중단 점을 설정합니다. 각 호출. 분명히 수정 교환해야합니다 OldCustomEditChange를 호출하십시오.

  2. .dfm에서 EditChange가 하나의 이벤트 (다중 이벤트 아님)에만 할당되고 OldCustomEditChange가 전혀 지정되지 않았는지 확인하십시오. 게시 된 호출 스택에 기반