문제

나는 과거에 사라진이 불쾌한 벌레를 가지고 있었지만 지금은 꽤 오랫동안 돌아 왔습니다.

Tasmjob 객체 (TobjectList에서 파생 된)에 생성되어로드 된 두 개의 TSAM 객체 (tpersistent에서 파생)가 있습니다.

런타임에 양식은 TStringGrid를 생성 한 다음 ASMJOB를 생성하여 두 개의 SAM 객체를 생성합니다 (각각 디스크에서 일부 데이터를로드). ASMJOB도 그리드에 할당됩니다. 양식이 파괴되면 그리드는 asmjob을 제거하여 ASMJOB를 처리하여 TSAM 객체를 해방시킵니다. 문제는 다음과 같습니다. 첫 번째 객체는 문제가 발생했지만 두 번째 객체는 상속 된 방법 (파괴 파괴자)이 호출되면 죽습니다.

전체 프로그램에서 FreeAndnil을 사용하여 물체를 제거합니다. TSAM 객체는 NIL이 아닙니다 !!!!! 그래서 이것은 객체를 자유롭게하려는 첫 번째 시도입니다. 객체 내부의 데이터조차 일관성이 있습니다.

프로그램의 중추는 다음과 같습니다.

**Create:**

Form -> StringGrid
     -> AsmJob -> Sam1, Sam2
StringGrid.AsmJob:= AsmJob;


**Free:**

Form -> StringGrid -> AsmJob -> Sam1, Sam2

나는 객체가 출시 된 후에 객체를 두 번 무료로 쓰거나 덮어 쓰는 곳을 정말로 이해하지 못한다.


편집하다:

내가 얻은 오류 중 일부 :

  • FASTMM은 무료 블록 스캔 작업 중에 오류를 감지했습니다. Fastmm은 해제 후 블록이 수정되었음을 감지했습니다.

  • FASTMM은 무료 블록 스캔 작업 중에 오류를 감지했습니다. 블록 헤더가 손상되었습니다.

세부 사항:

The current thread ID is 0x19C, and the stack trace (return addresses) leading to this error is: 
402E77 [System][@FreeMem] 
4068DC [System][@DynArrayClear] 
405E2D [System][@FinalizeArray] 
405D31 [System][@FinalizeRecord] 
40432F [System][TObject.CleanupInstance] 
404272 [System][TObject.FreeInstance] 
404641 [System][@ClassDestroy] 
4D313E [UnitSam.pas][TSam.Destroy][297] 
4042BF [System][TObject.Free] 
4149ED [SysUtils][FreeAndNil] 
4D9C0A [UnitAsmJob.pas][UnitAsmJob][TAsmJob.Destroy][180]  

IDE에서 "범위 점검"을 포함하여 모든 "디버그"옵션이 있습니다. 또한 FASTMM4는 매우 공격적인 디버그 모드로 설정되었습니다. Fastmm이 없거나 디버거 외부가 없으면 프로그램이 잘 작동하지만 버그가 더 이상 없다는 것을 의미하지는 않습니다. 실제로 Fastmm을 설치할 때까지 1 년 이상 (아마도 1 년 이상) 작동했습니다.


편집하다:

모두에게 감사합니다. 아니요, 나는 좋은 방향으로 조금 움직이고 있다고 느낍니다.

프로그램의 구조는 더 복잡합니다. 원래 게시물을 작게 유지하기 위해 백본 만 제공했습니다. 그러나 도대체 이미 더 커졌습니다. :) 따라서 TSAM 객체는 디스크에서 데이터를로드하는 데 사용됩니다. 각 객체에 하나의 파일. 그들은 또한 처리 및 데이터 검증을 수행하고 있습니다. 이 TSAM 각각에 대해 TSAM 객체에 포함 된 데이터를 화면에 표시하는 그래픽 객체도 있습니다. TSTRINGGRID의 각 줄에는 TSAM의 데이터가 표시되지만 텍스트로 표시됩니다.

내가 가진 한 가지 질문 : 오류가 어디에 있는지 알아 내기 위해 프로그램을 작은 조각으로 나누면 오류가 여전히 나타납니다. 아니면이 특정 구성에만 나타날 수 있습니까?


"ASMJOB가 TStringGrid에 ASMJOB을 파괴하도록 어떻게 할당 되나요?"

MyGrid = TStringGrid
  public 
    AsmJob: TAsmJob; 
  end; 

그런 다음 tform.create (그리드를 보유하는 양식) 어딘가에 있습니다.

MyGrid.AsmJob=AsmJob; 

그리고 Mygrid의 소멸자에서 나는 다음과 같습니다.

begin 
  FreeAndNil(AsmJob); 
  inherited 
end;
도움이 되었습니까?

해결책

이 오류는 코드가 내부 메모리 관리자의 구조를 손상했음을 의미합니다. 통화 스택은 MM이 이것을 감지했을 때 포인트를 나타냅니다. 이것은 오류 경로 나 그와 관련된 것이 아닙니다. 실제 오류는이 순간 이전에 발생합니다. 언급 된 클래스와 관련이 있거나 관련이 없을 수도 있습니다.

전체 디버그 모드에서 "범위 검사 오류"옵션 (Compile, Compile을 잊지 마십시오) 및 Fastmm을 사용해야합니다 (CheckheapforCorprestion, CatchuseOffreedInterfaces и DetectMMMOPERATIONSAFTERUNINSTALL 옵션 활성화)..

또한 FullDebugmodescanmemorypoolbeforeeeeeeeeee는 전 세계 변수를 켜서 문제가 발생한 직후 거의 오류를 얻을 수 있지만이 옵션은 실행이 많이 느려집니다.

아마도 최선의 선택은 주기적으로 ScanMemoryPoolforCorruptions 호출입니다. 한 곳에서 전화하십시오. 오류가 있습니까? 더 빨리 전화하십시오. 여전히 오류가 있습니까? 더 빨리 전화하십시오. 오류가 없습니까? 당신의 문제는 그 마지막 전화 사이에 있습니다. 이제 FullDebugmodescanmemorypoolbeforeeeeeeeeee는 변수를 사용하여 정확한 위치를 얻을 수 있습니다. 이 코드 영역에서만 켜고 바로 뒤로 켜십시오.

매우 유사한 오류가 있습니다. "Fastmm은 해제 후 블록이 수정되었음을 감지했습니다". 이 경우 코드는 내부 구조가 아니라 전혀 사용하지 않는 다른 메모리 ( "자유 메모리")를 수정합니다.

BTW, 오류는 이중 무료가 아닙니다! 이것이 이중 무료 호출 인 경우 Fastmm은 명시 적으로 알려줄 것입니다 (사용하지 않거나 존재하지 않는 메모리 블록을 자유롭게하려고 할 때 쉽게 감지 할 수 있습니다) : "무료/재 할당을 시도했습니다. 할당되지 않은 블록 ".

다른 팁

블록 헤더가 손상되면 일반적으로 어떤 종류의 안전하지 않은 작업을 수행함으로써 무언가가 메모리를 덮어 쓰고 있음을 의미합니다. 작업에서 원시 포인터 또는 어셈블리 코드를 사용하고 있습니까? 또한 범위 점검과 경계 확인을 끄면 켜고 재건을 켜십시오. 그들은 이런 종류의 문제를 많이 포착하는 데 도움이 될 수 있습니다.

코드 어딘가에 객체가 해제 될 때 객체가 쓰여지는 논리 경주가있을 수 있습니다. Null-Checks 및 기타 IPC 메커니즘 (잠금 목록 등)을 추가하여 그렇지 않은지 확인하십시오.

또 다른 옵션은 코드를 서브 클래스하여 로깅을 추가하고 객체에 순차적으로 액세스하는지 확인하는 것입니다.

몇 가지와 코드를 볼 수 없기 때문에 묻습니다.

다음 코드가 주어지면 :

procedure TForm1.FormCreate(Sender: TObject);
var
   wObjLst : TObjectList;
begin
   wObjLst := TObjectList.Create;
   try
      wObjlst.OwnsObjects := true;
      wObjlst.Add(TPersistent.Create);
      wObjlst.Add(TPersistent.Create);
   finally
      freeandnil(wObjlst);
   end;
end;

이것은 Out 오류와 함께 작동합니다.

당신은 그것을 말합니다

런타임에 양식은 TStringGrid를 생성 한 다음 ASMJOB를 생성하여 두 개의 SAM 객체를 생성합니다 (각각 디스크에서 일부 데이터를로드). ASMJOB도 그리드에 할당됩니다. 양식이 파괴되면 그리드는 asmjob을 제거하여 ASMJOB를 처리하여 TSAM 객체를 해방시킵니다. 문제는 다음과 같습니다. 첫 번째 객체는 문제가 발생했지만 두 번째 객체는 상속 된 방법 (파괴 파괴자)이 호출되면 죽습니다.

첫 번째 질문은 TStringGrid가 ASMJOB를 파괴하도록 ASMJOB가 어떻게 TStringGrid에 할당 되는가입니다.

둘째, 왜 TobjectList의 자손을 만들어 두 개의 객체를 저장 한 다음 스스로 만들고 TobjectList가 위에 표시된대로 파괴하는 대신 자유롭게 자유롭게 해제하십시오.

시도해야 할 또 다른 것은 전체 Fastmm4 패키지를 다운로드하는 것입니다. Fastmm.sourceforge.net, 그것을 설치하고 FullDebug DLL을 사용하여 어떤 객체가 실패했는지 정확히 추적하십시오. 당신과 나는 그것이 SAM 대상 중 하나라고 가정하고 있으며 그렇지 않을 수도 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top