2008-11-14 13 views
8

नीचे दिए गए कोड को निष्पादित करते समय EAccessViolation क्यों उठाया जाता है?TList.Remove() एक EAccessViolation त्रुटि का उत्पादन क्यों कर रहा है?

uses 
    Generics.Collections; 
    ... 

var 
    list: TList<TNotifyEvent>; 
    ... 

begin 
    list := TList<TNotifyEvent>.Create(); 
    try 
    list.Add(myNotifyEvent); 
    list.Remove(myNotifyEvent); // EAccessViolation at address... 
    finally 
    FreeAndNil(list); 
    end; 
end; 

procedure myNotifyEvent(Sender: TObject); 
begin 
    OutputDebugString('event'); // nebo cokoliv jineho 
end; 

उत्तर

0

ऊपर कोड TForm1 में प्रयोग किया जाता है ...

uses 
    Generics.Collections; 

procedure TForm1.Button1Click(Sender: TObject); 
var 
    list: TList<TNotifyEvent>; 
begin 
    list := TList<TNotifyEvent>.Create(); 
    try 
    list.Add(myNotifyEvent); 
    list.Remove(myNotifyEvent); // EAccessViolation at address... 
    finally 
    FreeAndNil(list); 
    end; 
end; 
procedure TForm1.myNotifyEvent(Sender: TObject); 
begin 
    OutputDebugString('event'); // nebo cokoliv jineho 
end; 
+0

हम्म, यह वास्तव में आपके प्रश्न का उत्तर नहीं है। मुझे लगता है कि आपको इसे अपने प्रश्न में कोड के साथ मर्ज करना चाहिए (जो, जैसा कि अब है, अमान्य है क्योंकि प्रश्न में दिखाए गए 'myNotifyEvent'' TNotifyEvent' हस्ताक्षर से मेल नहीं खाता है (यह वहां कोई विधि नहीं है) –

5

यह एक बग की तरह दिखता है।

यदि आप डीबग डीसीयू के साथ संकलित करते हैं (आमतौर पर तब तक ऐसा न करें जब तक कि आप अपनी संवेदना को खोना नहीं चाहते!) आप देखते हैं कि तुलनाकर्ता को एक कॉल गलत हो गया था। तुलनात्मक फ़ंक्शन का एक (संभवतः वैकल्पिक) तीसरा मान सेट नहीं है और एक्सेस उल्लंघन का कारण बनता है।

तो संभवतः आप एक सामान्य सूची में विधि पॉइंटर्स नहीं डाल सकते हैं।

ठीक निम्नलिखित काम करता है:

uses 
    Generics.Defaults; 

type 
    TForm4 = class(TForm) 
    ... 
    private 
    procedure myNotifyEvent(Sender: TObject); 
    end; 

TComparer<T> = class (TInterfacedObject, IComparer<T>) 
public 
    function Compare(const Left, Right: T): Integer; 
end; 

implementation 

uses 
    Generics.Collections; 

var 
    list: TList<TNotifyEvent>; 
begin 
    list := TList<TNotifyEvent>.Create(TComparer<TNotifyEvent>.Create); 
    try 
    list.Add(myNotifyEvent); 
    list.Remove(myNotifyEvent); 
    finally 
    FreeAndNil(list); 
    end; 
end; 

procedure TForm4.myNotifyEvent(Sender: TObject); 
begin 
    ShowMessage('event'); 
end; 

{ TComparer<T> } 

function TComparer<T>.Compare(const Left, Right: T): Integer; 
begin 
    Result := 0; 
end; 

आप possiby कुछ और खुफिया ;-) के साथ, अपने स्वयं के comparer परिभाषित करने के लिए किया है।

+0

दिखता है मुझे भी एक बग की तरह। –

1

क्या TList<T> पर एक कस्टम तुलनाकर्ता पास करना संभव है? मेरे पास डी 2009 मेरे सामने नहीं है, इसलिए इसे आजमाया नहीं जा सकता है।

+0

हाँ आप अधिभारित कन्स्ट्रक्टर पर एक को पास कर सकते हैं। –

3

एक्सेस उल्लंघन उल्लंघन तुलनाकर्ता के कारण होता है। मैं इस एक पैच में तय किया गया था पर शक लेकिन समस्या अभी भी बनी रहती (कम से कम डेल्फी 2009 में) यदि आप एक TObjectList उपयोग करती हैं इसलिए मैं सिर्फ सरल समाधान के साथ अद्यतन करने हूँ:

TList<TNotifyEvent>.Create(TComparer<TNotifyEvent>.Default); 

या मेरे मामले

में
TObjectList<TNotifyEvent>.Create(TComparer<TNotifyEvent>.Default); 
+0

यह बग अभी भी xe4 के साथ मौजूद है: / –