2012-04-13 28 views
6

Sử dụng các tệp nguồn giống hệt nhau cho Fortran .dll tôi có thể biên dịch chúng bằng Compaq Visual Fortran 6.6C hoặc Intel Visual Fortran 12.1.3.300 (IA-32). Vấn đề là việc thực hiện thất bại trên nhị phân Intel, nhưng hoạt động tốt với Compaq. Tôi đang biên dịch 32 bit trên hệ thống Windows 7 64 bit. Trình điều khiển cuộc gọi .dll được viết bằng C#.Ngăn xếp tràn trên cuộc gọi chương trình con chỉ khi được biên dịch với Intel Visual Fortran và tiền phạt khi biên dịch bởi Compaq Visual Fortran

Thông báo lỗi đến từ cuộc gọi _chkstk() đáng sợ khi một chương trình con nội bộ được gọi (được gọi từ thường trình nhập .dll). (SO trả lời trên chkstk())

Thủ tục trong câu hỏi được khai báo là (tha thứ các định dạng tập tin cố định)

SUBROUTINE SRF(den, crpm, icrpm, inose, qeff, rev, 
&    qqmax, lvtyp1, lvtyp2, avespd, fridry, luin, 
&    luout, lurtpo, ludiag, ndiag, n, nzdepth, 
&    unit, unito, ier) 

    INTEGER*4 lvtyp1, lvtyp2, luin, luout, lurtpo, ludiag, ndiag, n, 
&   ncp, inose, icrpm, ier, nzdepth 
    REAL*8 den, crpm, qeff, rev, qqmax, avespd, fridry   
    CHARACTER*2 unit, unito 

và kêu gọi như thế này:

 CALL SRF(den, crpm(i), i, inose, qeff(i), rev(i), 
&    qqmax(i), lvtyp1, lvtyp2, avespd, fridry, 
&    luin, luout, lurtpo, ludiag, ndiag, n, nzdepth, 
&    unit, unito, ier) 

với thông số kỹ thuật biến tương tự trừ crpm , qeff, revqqmax là các mảng chỉ sử dụng các thành phần i-th cho mỗi cuộc gọi SRF().

Tôi hiểu các vấn đề có thể xảy ra nếu đối số có kích thước lớn hơn 8kb, nhưng trong trường hợp này, chúng tôi chỉ có đối số được chuyển là 7 x real(64) + 11 x int(32) + 2 x 2 x char(8) = 832 bits.

Tôi đã làm việc thực sự khó khăn để di chuyển đối số (đặc biệt là mảng) vào một mô-đun, nhưng tôi vẫn gặp lỗi tương tự

error.

Các dissasembly từ .dll Intel là

intel

Các dissasembly từ Compaq .dll là

compaq

bất cứ ai có thể đưa ra bất kỳ đề xuất về những gì là gây ra SO, hoặc làm thế nào để gỡ lỗi nó?

PS. Tôi đã tăng không gian ngăn xếp dành riêng cho hàng trăm Mb và sự cố vẫn tiếp diễn. Tôi đã cố gắng bỏ qua các cuộc gọi chkstk() trong dissasembler nhưng trong tai nạn chương trình. Kiểm tra ngăn xếp bắt đầu từ địa chỉ 0x354000 và lặp lại xuống 0x2D2000 nơi nó gặp sự cố khi truy cập trang bảo vệ. Địa chỉ dưới cùng của ngăn xếp là 0x282000.

+0

Bạn đang sử dụng các tùy chọn trình biên dịch nào trong mỗi trường hợp? Hãy thử biên dịch tất cả các cờ cảnh báo lỗi mà bạn có thể nghĩ là đã bật. Bước đầu tiên tôi có xu hướng sử dụng '-std -check all -Warn all, nodec, interfaces, declarationations -gen_interfaces -g -C -traceback -fpe0 -fp-stack-check' với ifort. – Chris

+0

Tôi hy vọng bạn đã phát hiện ra lỗi số học của riêng bạn bây giờ, nhưng tổng số 832 byte của bạn phải là 832 bit. Nó không phải luôn luôn là trường hợp, hoặc là, mỗi nhân vật được đại diện bởi một byte: điều này có xu hướng khác nhau với trình biên dịch và nền tảng. Với một trình biên dịch cập nhật, kích thước của các 'đơn vị lưu trữ' khác nhau có sẵn như là các hằng số được định nghĩa trong mô-đun nội tại ISO_FORTRAN_ENV. –

+0

Cả hai ý kiến ​​trên đều cho tôi một cái gì đó để làm việc. Tôi sẽ điều tra thêm. Có thể có một tham nhũng ngăn xếp mà 'CVF' không bắt và bằng cách nào đó thổi qua nó. Có rất nhiều điều xảy ra trong mã như nhiều nhà phát triển đã chạm vào nó từ những năm 80 khi nó được viết lần đầu tiên. – ja72

Trả lời

2

Bạn đang quay người đưa tin. Mã Compaq được tạo ra cũng là gọi _chkstk(), sự khác biệt là nó đã gạch chân nó. Một tối ưu hóa phổ biến. Sự khác biệt chính giữa hai đoạn là:

mov eax, 0D3668h 

vs

sub esp, 233E4h 

Các giá trị mà bạn nhìn thấy sử dụng ở đây là số lượng ngăn xếp không gian theo yêu cầu của chức năng. Mã Intel yêu cầu 0xd3668 byte = 865869 byte.Mã Compaq yêu cầu 0x233e4 = 144356. Sự khác biệt lớn. Trong cả hai trường hợp, đó là một số lượng lớn nhưng Intel đang trở nên quan trọng, một chương trình thường có một megabyte stack. Ầm ầm lên 0,86 megabyte của nó đang đẩy nó rất gần, tổ chức một vài cuộc gọi chức năng và bạn đang nhìn vào tên của trang web này.

Những gì bạn cần tìm hiểu, tôi không thể trợ giúp vì nó không nằm trong đoạn mã của bạn, đó là lý do tại sao chức năng được tạo ra của Intel cần rất nhiều không gian cho các biến cục bộ của nó. Cách giải quyết là sử dụng cửa hàng miễn phí để tìm không gian cho các mảng lớn. Hoặc sử dụng tùy chọn của liên kết/STACK để yêu cầu thêm không gian ngăn xếp (đoán tại tên tùy chọn).

+0

Cảm ơn thông tin. Bạn có thể xây dựng trên _use store_ miễn phí để tìm không gian? Có rất nhiều tính toán xảy ra trong mảng này, điền vào một mảng 18.000.000 các phần tử của 'REAL * 8'. – ja72

+1

Tôi khá già nhưng chưa đủ tuổi. Xem các câu lệnh ALLOCATE và DEALLOCATE trong tài liệu tham khảo Fortran yêu thích của bạn. –

+0

Các mảng này được cấp phát trong VBA và được truyền cho Fortran '.dll'. Chúng không được cấp phát trong Fortran, vì vậy tôi không thể sử dụng các mảng phân bổ. Việc đăng tải đã rất hữu ích mặc dù, như tôi vẫn đang tìm kiếm một câu trả lời ở đây. – ja72

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