2011-11-08 19 views
8

में शून्य अपवाद द्वारा फ़्लोटिंग पॉइंट डिवीजन मेरा ऐप डेल्फी 5 में लिखा गया है। मैं बग को ट्रैक करने के लिए madExcept का उपयोग कर रहा हूँ। मैंने "फ्लोटिंग पॉइंट डिवीजन शून्य द्वारा" अपवाद को ट्रैक किया, जहां यह नहीं होना चाहिए। कोड सेगमेंट, जहां इसे उठाया जाता है, निम्नानुसार जाता है:डेल्फी 5

val:=100*Power(1.25,c); 

जहां 'सी' वास्तव में हमेशा '1' मान होता है।

लॉग का स्टैक ट्रेस: ​​

main thread ($338f8): 
00403504 +010 MyApp.exe System 1970 +5 @FRAC 
00479148 +058 MyApp.exe Math    Power 
007ae8a6 +262 MyApp.exe MyClass 1962 +36 TMyClass.FormMouseWheel 

मैं एक बिंदु है, जहां एक-विभाजन होने पर फिर से किया था अपवाद था, फिर भी भाजक एक चर, जो भी मूल्य था '1' जब अपवाद हुआ। कि मैं डीबग और पुन: पेश करने में सक्षम था।

मेरा प्रश्न: मुझे क्या याद आ रही है? क्या फ्लोटिंग पॉइंट डिवीजन के बारे में कुछ झूठे सकारात्मक हैं जिनके बारे में मुझे जानकारी नहीं है?

इसके अलावा: मैं अपवाद बिंदुओं पर किसी भी सी ++ डीएलएल का उपयोग नहीं कर रहा हूं क्योंकि वे एफपी डिवीजनों को अलग-अलग संभालते हैं (अपवाद बढ़ाने के बजाय NaN या +/- INF लौटाते हैं)।

किसी भी पॉइंटर्स की सराहना की।

+3

बहुत व्यावहारिक नहीं लगता है। मुझे नहीं लगता कि आपके डिबगिंग टूल आपको सही जगह पर इंगित कर रहे हैं, या शायद वेरिएबल वे नहीं हैं जो आप सोचते हैं कि वे हैं। –

+0

याद रखें कि डी 5 में पहले से ही यह था, लेकिन क्या आपने यह जांचने की कोशिश की कि सीपीयू/एफपीयू दृश्य में क्या हो रहा है जब उस कोड को निष्पादित किया गया हो? –

+0

@ldsandon बेशक डी 5 को पहले से ही Alt-F2 का उपयोग करने और CPU/FPU दृश्य में कदम रखने की अनुमति है। अच्छा विचार। लेकिन मुझे लगता है कि एक unhandled एफपीयू अपवाद 'System._Frac' कोड में तोड़ देगा। –

उत्तर

8

मैं बस निम्नलिखित कोड की कोशिश की:

procedure TTTest.FormCreate(Sender: TObject); 
var v: extended; 
    one: extended; 
begin 
    one := 1.0; 
    v := 100*Power(1.25,one); 
end; 

यह सिर्फ संकलित और डेल्फी में होने की उम्मीद के रूप में चलता 5.

मेरा अनुमान शून्य झंडा प्रति विभाजन अपने कोड के बाहर स्थापित किया जा सकता है कि है (यहां तक ​​कि यदि आप सी ++ कोड से लिंक नहीं करते हैं, तो डायरेक्ट एक्स को कॉल करना या ऐसा ही प्रभाव हो सकता है), लेकिन _Frac में बाद में उठाया गया।

के मानक कार्यान्वयन में Frac पर एकमात्र कॉल Frac(Exponent) = 0.0 का परीक्षण करना है।

डेल्फी 5 और डेल्फी 6. के बीच Frac के कार्यान्वयन में एक संशोधन

यहाँ डेल्फी 5 संस्करण है हुई:

procedure  _FRAC; 
asm 
    FLD  ST(0) 
    SUB  ESP,4 
    FNSTCW [ESP].Word  // save 
    FNSTCW [ESP+2].Word // scratch 
    FWAIT 
    OR  [ESP+2].Word, $0F00 // trunc toward zero, full precision 
    FLDCW [ESP+2].Word 
    FRNDINT 
    FWAIT 
    FLDCW [ESP].Word 
    ADD  ESP,4 
    FSUB 
end; 
:

procedure  _FRAC; 
asm 
    FLD  ST(0) 
    SUB  ESP,4 
    FSTCW [ESP] 
    FWAIT 
    FLDCW cwChop 
    FRNDINT 
    FWAIT 
    FLDCW [ESP] 
    ADD  ESP,4 
    FSUB 
end; 

यहाँ डेल्फी 6 संस्करण है

उपर्युक्त कोड से, आप पाएंगे कि निम्नलिखित आदेशों ने डेल्फी 6 जारी किए जाने से पहले देरी अपवादों को उठाया: ट्रंक, फ्रैक, सेइल ।

तो मुझे लगता है कि आपको डेल्फी 5 के साथ एक समस्या का सामना करना पड़ा, जिसे डेल्फी 6 के साथ तय किया गया है।आप इस तरह की शक्ति का अपने स्वयं के संस्करण का उपयोग करने के लिए हो सकता है:

function Power(Base, Exponent: Extended): Extended; 
begin 
    if Exponent = 0.0 then 
    Result := 1.0    { n**0 = 1 } 
    else if (Base = 0.0) and (Exponent > 0.0) then 
    Result := 0.0    { 0**n = 0, n > 0 } 
    else 
    Result := Exp(Exponent * Ln(Base)) 
end; 
+0

महान उत्तर जिसने मेरे लिए समस्या का अधिकार दिया। मामूली नाइट-पिकिंग, लेकिन टिप्पणियों के साथ उत्तर में सुधार किया जा सकता है कि कम से कम मुख्य लाइनों के लिए असेंबली की प्रत्येक पंक्ति क्या कर रही है। या वैकल्पिक रूप से, संक्षेप में बताएं कि प्रत्येक _एफआरएसी प्रक्रिया क्या करती है (स्टैक पर पुराने सीडब्ल्यू को दबाएं, नया सीडब्लू सेट करें, ऑपरेशन करें, स्टैक से पुरानी सीडब्लू पॉप करें, उस तरह की चीज)। X86 असेंबली में हमारे बारे में अच्छी तरह से ज्ञात नहीं है उन लोगों के लिए मदद करेगा। :) –

2

किसी भी तरह से नहीं एक निश्चित जवाब है, लेकिन ...

एफपीयू संबंधित अपवाद जहां नहीं होना चाहिए, एफपीयू ढेर ठीक से साफ नहीं किया जा रहा से संबंधित हो सकता। हमें एक ही चरण में समान समस्याएं थीं, हालांकि हमने अमान्य फ़्लोटिंग प्वाइंट ऑपरेशन अपवादों का अनुभव किया था।

यह आलेख: Delphi bug of the day: FPU stack leak जहां किसी ने S := S + '*'; द्वारा फेंक दिए गए अमान्य फ़्लोटिंग प्वाइंट ऑपरेशन अपवाद के कारण को ट्रैक किया, तो हमें इस समस्या को हल करने में मदद मिली।

0

आप TWebBrowser या EmbeddedWB की तरह किसी भी आईई webbrowser घटक का उपयोग कर रहे हैं?

यदि हां, तो यह समझा सकता है: https://forums.embarcadero.com/thread.jspa?messageID=334125&tstart=0

यह भी कुछ है कि इस समस्या को ठीक कर सकते हैं, भले ही आप ऊपर का वर्णन करता है जेरोन द्वारा प्रदान की कड़ी के रूप में एक webbrowser (Set8087CW) उपयोग नहीं कर रहे हैं।