2014-12-04 19 views
8

Đối với những ngày tôi đang đấu tranh khó khăn (nhưng vô ích) với mặt nạ ngoại lệ.Trường hợp ngoại lệ mặt nạ trong Delphi

Tôi đã phát triển một ứng dụng tạo ra các phép tính điểm nổi nặng trên hàng trăm nghìn bản ghi. Rõ ràng là mã phải có khả năng xử lý các ngoại lệ, đặc biệt là các mã liên quan đến tính toán dấu phẩy động: Overflow, ZeroDivide, vv ..

Ứng dụng chạy đúng theo Windows 7 (32bit hoặc 64bit) với nhiều loại bộ vi xử lý khác nhau, nếu lỗi xảy ra các điều kiện được xử lý đúng cách, một ngoại lệ được nâng lên và hồ sơ được loại bỏ.

Thật không may, các sự cố bắt đầu khi tôi khởi chạy ứng dụng chỉ ở nơi dự định chạy: trên một máy chủ chuyên dụng với CPU Intel Xeon E5-2640 v2 và Windows Server 2003 R2. Ở đây các ngoại lệ không được nâng lên: các bản ghi có lỗi sẽ không bị loại bỏ và do đó kết quả bị ô nhiễm bởi các giá trị số này mà máy mô tả +INF hoặc -INF.

Vấn đề là trên máy chủ các thiết lập mặc định của mặt nạ lỗi là khác nhau từ những người mà chúng ta tìm thấy trong Windows 7. Đặc biệt, kêu gọi các thủ tục GetExceptionMask trên máy chủ theo mặc định tôi thấy exZeroDivide trong khi nếu gọi GetExceptionMask trên Windows 7 ngoại lệ này không bị che khuất. Kết quả là những gì tôi đã nói: chạy ứng dụng trên máy chủ những ngoại lệ này không được nâng lên nhưng được xử lý bởi bộ xử lý trả về cực đoan và "gây ô nhiễm" các giá trị số.

Ok, đừng hoảng sợ, tôi nói, bạn chỉ cần gọi (ví dụ: trong phần khởi tạo) SetExceptionMask không bao gồm exZeroDivide, nhưng không hoạt động. Hoặc tốt hơn, mặc dù ngay sau khi gọi SetExceptionMask ngoại lệ exZeroDivide không còn bị che khuất, khi được thực thi mã có tính toán dấu phẩy động, tập hợptrả về GetExceptionMask vẫn chứa exZeroDivide và do đó nếu xảy ra lỗi ngoại lệ.

Bất cứ ai có thể cho tôi biết cách gọi đúng SetExceptionMask là gì?

Đó là lý do khiến mặc định mặt nạ có thể khác với máy tính và cách khác? hệ điều hành hoặc loại bộ vi xử lý?

Cảm ơn.

+2

Đây là mô tả hay nhưng bạn có thể đăng một số mã mẫu tạo ra ngoại lệ và mẫu để cho biết cách bạn đang cố xử lý mặt nạ không? Điều đó sẽ giúp chúng tôi dễ dàng hơn trong việc giúp bạn tìm ra giải pháp. :) –

+0

Tôi đồng ý, khó mà nói mà không thấy bạn đang làm như thế nào. Tôi khuyên bạn nên bắt đầu một ứng dụng thử nghiệm hoàn toàn mới để tái tạo hành vi này và chia sẻ mã đó với chúng tôi. –

+1

Có vẻ như một thứ gì đó đang được đưa vào quá trình của bạn trên Server 2003 - trình kiểm tra virus, móc toàn cục, tiện ích theo dõi hệ thống khác? - đặt từ cờ FP với giá trị không chính xác. –

Trả lời

4

Nguyên nhân thông thường của việc này là bạn đang gọi đến mã của bên thứ ba để xóa các mặt nạ. Nó có thể là một thư viện mà bạn đang cố ý sử dụng nhưng nhiều khả năng nó là một cái gì đó mà bạn không đặc biệt nhận thức được gọi. Một ví dụ phổ biến của điều này là trình điều khiển máy in. Đây là những khét tiếng cho việc thay đổi cờ điều khiển dấu phẩy động.

Bước tiếp theo là xác định một phần của mã thay đổi cờ điều khiển. Tôi đề nghị bạn thêm gỡ lỗi ghi nhật ký. Các cuộc gọi đến OutputDebugString sẽ đủ, nhưng bạn sẽ làm tốt để sử dụng thư viện ghi nhật ký nâng cao hơn. Ghi lại trạng thái của các cờ điều khiển khi chương trình của bạn thực thi. Bạn sẽ cần một vài chu kỳ thêm cuộc gọi đăng nhập, chạy, đọc nhật ký, trước khi bạn có thể xác định vị trí thủ phạm. Khi bạn đã tìm thấy mã bên ngoài thay đổi cờ, hãy đảm bảo bạn khôi phục chúng sau khi mã bên ngoài thực hiện.

Đây là một lĩnh vực phức tạp mà tôi sợ. Nó không phải dễ dàng để có được quyền. Bên ngoài mã đôi khi chơi nhanh và lỏng lẻo với các cờ điều khiển như thể mã đó là mã duy nhất tồn tại. Các RTL Delphi không phải là lớn nhất tại xử lý cờ kiểm soát hoặc. Nó có lẽ không được biết rằng Set8087CW không phải là threadsafe, ví dụ.

Cá nhân tôi đã trải qua cuộc đấu tranh của bạn với ứng dụng điểm nổi của riêng tôi. Nhưng bạn sẽ có thể giải quyết những vấn đề như vậy. Chúc may mắn!

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