2011-09-08 14 views
21

मुझे यकीन था कि यह मेरे लिए काम करता था, और मैंने इसे नेट (जोलीन स्मिथ और डेविड मूरहाउस) पर देखा है। डी 2007 और एक्सई 2 परीक्षण में एक साधारण कार्यक्रम में बस कोशिश करने के बाद, यह संशोधित संदेश नहीं रखता है। जैसे ही "raise" होता है, संदेश मूल अपवाद पर वापस आ जाता है।पुन: उठाए जाने पर एक अपवाद वस्तु में परिवर्तन क्यों खो गए हैं?

मुझे क्या अंधकारमय स्पष्ट चीज़ याद आ रही है? विकल्प "अपवाद को बढ़ाएं। बनाएं (...)" लेकिन मैं सिर्फ मूल अपवाद को श्रृंखला का बैक अप लेना चाहता हूं, केवल प्रत्येक अपवाद ब्लॉक के साथ टैग की गई अतिरिक्त जानकारी के साथ।

var a: Integer; 
begin 
    try 
    a := 0; 
    Label1.Caption := IntToStr(100 div a); 
    except 
    on e: Exception do 
    begin 
     e.Message := 'Extra Info Plus the original : ' + e.Message; 
     raise; 
    end; 
    end; 
end; 

उत्तर

20

अच्छी तरह से मुझे उड़ाना! यह इतना गलत लग रहा था कि मुझे इसे खुद कोशिश करनी पड़ी, और तुम बिल्कुल सही हो! मैंने इसे इस तथ्य से कम कर दिया है कि यह एक ओएस अपवाद है (शून्य से विभाजित) जो ओएस द्वारा उत्पन्न होता है और डेल्फी द्वारा नहीं। यदि आप स्वयं को EIntError को आजमाते हैं और बढ़ाते हैं तो आपको अपेक्षित व्यवहार मिलता है, और जो आप ऊपर देखते हैं वह नहीं। ध्यान दें कि जब भी आप अपवाद उठाते हैं तो अपेक्षित व्यवहार होता है।

अद्यतन: System.pas इकाई में निम्न कोड जब अपवाद को फिर से उठाया है कहा जाता है:

{ Destroy any objects created for non-delphi exceptions } 

MOV  EAX,[EDX].TRaiseFrame.ExceptionRecord 
AND  [EAX].TExceptionRecord.ExceptionFlags,NOT cUnwinding 
CMP  [EAX].TExceptionRecord.ExceptionCode,cDelphiException 
JE  @@delphiException 
MOV  EAX,[EDX].TRaiseFrame.ExceptObject 
CALL TObject.Free 
CALL NotifyReRaise 

तो अगर अपवाद एक डेल्फी अपवाद (इस मामले एक OS में नहीं है अपवाद) तो (संशोधित) "डेल्फी" अपवाद मुक्त हो गया है और मूल अपवाद फिर से उठाया गया है, जिससे अपवाद में किए गए किसी भी बदलाव को फेंक दिया गया है। मामला समाप्त!

अद्यतन 2: (स्वयं की सहायता नहीं कर सका)। आप इसे निम्नलिखित कोड से पुन: पेश कर सकते हैं:

type 
    TThreadNameInfo = record 
    InfoType: LongWord; // must be $00001000 
    NamePtr: PAnsiChar; // pointer to message (in user address space) 
    ThreadId: LongWord; // thread id ($ffffffff indicates caller thread) 
    Flags: LongWord;  // reserved for future use, must be zero 
    end; 

var 
    lThreadNameInfo: TThreadNameInfo; 

    with lThreadNameInfo do begin 
    InfoType := $00001000; 
    NamePtr := PAnsiChar(AnsiString('Division by zero')); 
    ThreadId := $ffffffff; 
    Flags := $00000000; 
    end; 
    RaiseException($C0000094, 0, sizeof(lThreadNameInfo) div sizeof(LongWord), @lThreadNameInfo); 

मज़े करो!

+0

धन्यवाद मिशा। मैंने सोचा कि मैं साजिश खो रहा था! शून्य द्वारा – Paul

+0

डिवीजन ओएस अपवाद नहीं है। यह हार्डवेयर अपवाद है, जो सीपीयू द्वारा उठाया गया है (इस प्रकार, यह एसिंक अपवाद है)। ओएस और डेल्फी अपवाद दोनों सॉफ़्टवेयर अपवाद हैं, विशिष्ट कोड कॉल द्वारा उठाए गए हैं (इस प्रकार, यह सिंक अपवाद है)। इसलिए, प्रश्न में मुद्दा ओएस और डेल्फी अपवादों के बारे में नहीं है, लेकिन डेल्फी और गैर-डेल्फी अपवादों के बारे में है। "उठाना," मूल अपवाद को फिर से उठाता है (जो या तो हार्डवेयर या सॉफ़्टवेयर अपवाद हो सकता है), इसलिए डेल्फी ऑब्जेक्ट में कोई भी परिवर्तन केवल तभी संरक्षित किया जाएगा जब मूल अपवाद डेल्फी अपवाद था। यह काफी तार्किक है। – Alex

14

मिशा के स्पष्टीकरण को देखें। एक कामकाज के रूप में, आप यह कर सकते हैं:

except 
    on E: Exception do 
    begin 
    E := Exception(ExceptObject); 
    E.Message := '(Extra info) ' + E.Message; 
    AcquireExceptionObject; 
    raise E; 
    end; 
end; 
संबंधित मुद्दे