2011-11-08 18 views
8

Ứng dụng của tôi được viết bằng Delphi5. Tôi đang sử dụng madExcept để theo dõi lỗi. Tôi đã theo dõi một ngoại lệ "Điểm nổi hình ảnh bằng không", nơi nó không nên. Đoạn mã, nơi nó được nâng lên, như sau:Phân chia dấu chấm động bằng không ngoại lệ trong Delphi5

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

trong đó 'c' thực sự luôn có giá trị '1'.

Các vết đống của nhật ký:

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 

tôi đã ngoại lệ khác tại một thời điểm, nơi một bộ phận đã diễn ra, tuy nhiên số chia là một biến, mà cũng có giá trị '1' khi ngoại lệ đã xảy ra. Rằng tôi đã có thể gỡ lỗi và tái sản xuất.

Câu hỏi của tôi: tôi đang thiếu gì? Có một số tích cực sai về phân chia điểm nổi mà tôi không biết?

Hơn nữa: Tôi không sử dụng bất kỳ DLL C++ nào tại các điểm ngoại lệ vì chúng có xu hướng xử lý các đơn vị FP khác nhau (trả về NaN hoặc +/- INF thay vì tăng ngoại lệ).

Bất kỳ con trỏ nào được đánh giá cao.

+3

Âm thanh không chính xác lắm. Tôi không nghĩ rằng các công cụ gỡ lỗi của bạn đang trỏ bạn tới đúng nơi, hoặc có lẽ các biến không nắm giữ những gì bạn nghĩ. –

+0

Đừng nhớ nếu D5 đã có nó, nhưng bạn đã cố gắng kiểm tra những gì đang xảy ra trong khung nhìn CPU/FPU khi mã đó được thực hiện? –

+0

@ldsandon Tất nhiên D5 đã được phép sử dụng Alt-F2 và bước vào khung nhìn CPU/FPU. Ý tưởng tốt. Nhưng tôi đoán một ngoại lệ FPU không được giải quyết sẽ phá vỡ trong mã 'System._Frac'. –

Trả lời

8

Tôi chỉ cố gắng đoạn mã sau:

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

Nó chỉ biên dịch và chạy như mong đợi trong Delphi 5.

tôi đoán được rằng sự phân chia mỗi zero cờ có thể được thiết lập bên ngoài mã của bạn (thậm chí nếu bạn không liên kết với mã C++, hãy gọi Direct X hoặc có thể có cùng tác dụng), nhưng được nêu sau, trong _Frac.

Cuộc gọi duy nhất tới Frac trong việc triển khai chuẩn Power() là để kiểm tra Frac(Exponent) = 0.0.

Có một thay đổi trong việc thực hiện Frac giữa Delphi 5 và Delphi 6.

Dưới đây là phiên bản Delphi 5:

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

Dưới đây là phiên bản Delphi 6:

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; 

Từ mã trên, bạn sẽ thấy rằng các lệnh sau đây đã khiến các ngoại lệ bị trì hoãn được nâng lên trước khi Delphi 6 được phát hành: Trunc, Frac, Ceil .

Vì vậy, tôi đoán bạn đã gặp phải sự cố với Delphi 5, đã được sửa với Delphi 6.Bạn có thể phải sử dụng phiên bản riêng của bạn về điện, như thế này:

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

Câu trả lời tuyệt vời đã chỉ đúng cho vấn đề đối với tôi. Chọn nitro nhỏ, nhưng câu trả lời có thể được cải thiện với các bình luận giải thích những gì mỗi dây chuyền lắp ráp đang làm - ít nhất là cho các dòng chính. Hoặc cách khác, tóm tắt những gì mỗi thủ tục _FRAC làm (đẩy CW cũ trên stack, thiết lập CW mới, làm hoạt động, pop cũ CW từ stack, mà loại điều). Sẽ giúp cho những người trong chúng ta không thành thạo trong lắp ráp x86. :) –

2

Không phải là một câu trả lời dứt khoát bằng bất kỳ phương tiện, nhưng ...

ngoại lệ liên quan FPU nơi không nên có, có thể liên quan đến ngăn xếp FPU không được xoá hoàn toàn. Chúng tôi đã gặp sự cố tương tự ở một giai đoạn, mặc dù chúng tôi đã gặp phải các ngoại lệ về Hoạt động điểm không hợp lệ.

Bài viết này: Delphi bug of the day: FPU stack leak trong đó ai đó đã theo dõi lý do ngoại lệ cho Hoạt động điểm không hợp lệ được ném bởi S := S + '*';, đã giúp chúng tôi giải quyết vấn đề.

0

Bạn đang sử dụng TWebBrowser hoặc bất kỳ thành phần webbrowser IE như EmbeddedWB?

Nếu vậy, điều này có thể giải thích nó: https://forums.embarcadero.com/thread.jspa?messageID=334125&tstart=0

Nó cũng chứa một cái gì đó có thể khắc phục được vấn đề, ngay cả khi bạn không sử dụng một WebBrowser (Set8087CW) như các liên kết được cung cấp bởi Jeroen trên mô tả.

Các vấn đề liên quan