2013-04-26 4 views
42

게시 된 인터페이스 속성을 통해 서로 링크되는 구성 요소 집합을 작성했습니다. 이들은 등록되어 설계 패키지에 설치됩니다.게시 된 인터페이스 속성 버그 및 해결 방법

게시 된 인터페이스 속성을 사용하는 것이 Delphi에서 일반적이지 않으므로 놀랍지 않게 잘 작동하지 않는 것 같습니다.

구성 요소가 동일한 양식에있을 때 제대로 작동하지만 다른 양식의 구성 요소 간의 인터페이스 특성 링크로 인해 문제가 발생합니다.

다른 양식의 구성 요소에 대한 개체 링크와 달리 인터페이스 링크는 IDE에서 인식하지 못하는 것 같습니다. 내 말은 IDE에서 두 개의 폼을 열고 구성 요소 사이에 링크가있을 때 폼보기로 텍스트 (Alt + F12)로 전환하면 IDE가 올바르게 불평 할 수 있습니다.

속성이 인터페이스는 다음이 발생하지 않는 경우

Module 'UnitXXX.pas' has open descendents or linked modules. Cannot close.

그러나 , 무슨 대신 일이 그렇지 않으면 당신이있어, 링크가 절단되어 (당신이 참조를 취소 알림 메커니즘을 사용할 때 최선의 시나리오라는 것이다 잘못된 포인터가있는 왼쪽)

같은 버그로 인해 발생할 수있는 또 다른 문제는 IDE에서 프로젝트를 열 때 양식이 다시 열릴 것입니다 d는 정의되지 않았으므로 IDE는 다른 양식의 구성 요소에 대한 인터페이스 링크가있는 구성 요소를 포함하는 양식을 열려고 시도하지만 다른 양식은 아직 다시 작성되지 않습니다. 따라서 AV 또는 절단 된 링크가 효과적으로 생성됩니다.

위로 돌아가서 DatasetsDatasources을 사용하는 동안 양식간에 사라지는 링크와 비슷한 문제가 발생했기 때문에 다소 유사합니다.

임시 해결 방법으로 중복 게시 된 속성을 추가했습니다. 각 인터페이스 속성에 대해 TComponent으로 선언 된 속성을 추가했습니다. 이로 인해 델포이는 폼간에 링크가 있음을 알게되었지만 최소한의 말을하는 것은 추악한 해결 방법입니다.

이 문제를 해결하기 위해 할 수있는 일이 있는지 궁금합니다. 이것은 IDE 버그이며 직접 고칠 수는 없지만, 아마도이 버그를보다 효과적으로 해결하기 위해 무언가를 무시하거나 스트리밍 메커니즘에 후킹 할 수 있습니다.

스트리밍 메커니즘에 대해 자세히 들어 본 적이 없지만 Fixup 메커니즘이이 문제를 해결해야한다고 생각합니다. csFixupsTComponentState이 있으므로 가능한 해결 방법이 있기를 바랍니다.

편집 : 사용 D2007.

업데이트 :

새로운 업데이트 재현 예제는 비교 및 ​​구성 요소 스트리밍 대 인터페이스를 추적하기 쉽게 너무 http://www.filedropper.com/fixupbugproject2

에 추가 property ComponentReference: TComponent을 업로드했습니다.

문제를 내 깊이에서 약간 벗어난 어셈블러 수준으로 좁혔습니다.절차 GlobalFixupReferences에서

classes 단위에서 호출 :

function TInterfacedComponent.GetInterfaceReference: IInterface; 
begin 
// uncomment the code bellow to avoid exception 
{ if (csLoading in ComponentState) and (FInterfaceReference = nil) then 
    // leave result unassigned to avoid exception 
    else 
} 
    result := FInterfaceReference; // <----- Exception happens here 
end; 

당신이 코멘트에서 볼 수 있듯이, 유일한 방법은 내가 예외를 방지하기 위해 발견 : 결국 실행

(GetOrdProp(FInstance, FPropInfo) <> 0)

결과를 할당하지 않은 상태로 두는 것이지만, GlobalFixupReferences의 위의 비교가 링크를 절단하는 GetOrdProp <> 0로 인해 실패하기 때문에 기능이 중단됩니다. .

추적 깊은 예외의보다 정확한 위치는 MOV이 실패하는 이유

특히이 줄은, 그래서 read of address 0x80000000

{ Now we're into the less common cases. } 
@@NilSource: 
     MOV  ECX, [EAX]  // get current value 

을 제기

procedure _IntfCopy(var Dest: IInterface; const Source: IInterface); 단위 system에있는 어떤 ECX 잘못 또는 EAX 나는 잘 모른다.

+5

이것은 흥미로운 질문입니다. 내 개인적인 경험을 조금 넘어선 느낌입니다. 나는 신진 연구원을 돕는 데모 프로젝트가 있다면 용의자입니다. –

+1

@DavidHeffernan 재현하기가 매우 쉽기 때문에 IInterface 유형의 게시 된 속성이있는 TComponent 자손 만 있으면됩니다. 그것을 등록하고, 패키지를 설치하고, 두 개의 빈 양식 각각에 패키지를 내려 놓으십시오. 그건 그렇고, 나 스스로 할 수있어 너희들이 그걸로 놀아 보자. –

+1

그렇게했다면 도움이 될 것 같아. 우리를위한 장벽을 낮추십시오. –

답변

1

요약하면이 문제는 getter 메서드가있는 게시 된 인터페이스 속성에서만 발생하며 속성은 다른 폼/모듈의 구성 요소를 가리키며 폼/모듈은 아직 다시 만들어지지 않습니다. 이 경우 DFM 양식을 복원하면 AV가 발생합니다.

나는 버그가 GetOrdProp에서 ASM 코드에 확신하지만, 해결하기 위해 내 능력을 넘어, 그래서 가장 쉬운 해결 방법은 getter 메소드 대신 필드를 사용하여 속성에 직접 읽는 것입니다. 이것은 다행스럽게도 현재 나의 경우 충분히 좋다.

또는 인터페이스 대신 TComponent으로 속성을 선언 한 다음 TComponentProperty 자손을 작성하고 필수 인터페이스를 지원하지 않는 구성 요소를 필터링 할 때 ComponentMayBeSetTo을 재정의 할 수 있습니다. 그리고 물론 그것을 사용하여 등록 RegisterPropertyEditor

+0

이에 대한 QC 항목이 있습니까? –

+0

아니, 전 경험을 바탕으로 품질 관리를 믿지 않아요 ... –

+1

그것은 단지 문제를 영속시킵니다. 그들이 그것에 대해 모른다면 당신은 그것이 고쳐지지 않는다고 불평 할 수 없습니다. 만약 당신이 불평 할 수 있습니다 :) (내가 불평한다고 비난하는 것은 아니지만, 나는 당신이 의미하는 것을 얻습니다.) –