2012-04-13 7 views
6

Utilizzo di file di origine identici per un dll di Fortran Posso compilarli con Compaq Visual Fortran 6.6C o Intel Visual Fortran 12.1.3.300 (IA-32). Il problema è che l'esecuzione fallisce sul binario Intel, ma funziona bene con Compaq. Sto compilando 32-bit su un sistema Windows 7 64-bit. Il driver di chiamata .dll è scritto in C#.Overflow dello stack sulla chiamata di subroutine solo quando compilato con Intel Visual Fortran e corretto quando Compaq Visual Fortran è compilato

Il messaggio di errore deriva dalla temuta chiamata _chkstk() quando viene chiamata una subroutine interna (chiamata dalla routine di immissione .dll). (SO rispondere su chkstk())

La procedura in questione viene dichiarato come (pardon il formato di file fisso)

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 

e chiamato in questo modo:

 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) 

con le specifiche variabili simili tranne che per crpm , qeff, rev e qqmax sono matrici di cui solo gli elementi i-th vengono utilizzati per ogni chiamata SRF().

Capisco possibili problemi di stack se gli argomenti sono più di 8kb dimensioni, ma in questo caso abbiamo 7 x real(64) + 11 x int(32) + 2 x 2 x char(8) = 832 bits solo in argomenti passati.

ho lavorato duramente per spostare argomenti (specialmente array) in un modulo, ma io continuo a ricevere lo stesso errore

error.

Il dissasembly dal Intel .dll è

intel

Il dissasembly dal Compaq .dll è

compaq

Qualcuno può offrire qualche suggerimento su ciò che è causando la SO, o come eseguirne il debug?

PS. Ho aumentato lo spazio di stack riservato a centinaia di Mb e il problema persiste. Ho provato a saltare la chiamata chkstk() nel dissasembler ma in crash il programma. Il controllo dello stack inizia dall'indirizzo 0x354000 e scorre fino a 0x2D2000 dove si blocca durante l'accesso a una pagina di guardia. L'indirizzo inferiore dello stack è 0x282000.

+0

Quali opzioni del compilatore utilizzate in ciascun caso? Prova a compilare tutti i flag di errore di avviso che puoi pensare attivati. Come primo passo tendo ad usare '-std -check all -Warn all, nodec, interfacce, dichiarazioni -gen_interfaces -g -C -traceback -fpe0 -fp-stack-check' con ifort. – Chris

+0

Mi aspetto che tu abbia individuato il tuo errore aritmetico, ma il tuo totale di 832 byte dovrebbe essere 832 bit. Non è sempre il caso, inoltre, che ogni carattere sia rappresentato da un byte: questo tende a variare con il compilatore e la piattaforma. Con un compilatore aggiornato, le dimensioni delle varie "unità di memoria" sono disponibili come costanti definite nel modulo intrinseco ISO_FORTRAN_ENV. –

+0

Entrambi i commenti sopra mi danno qualcosa su cui lavorare. Investigherò di più. È possibile che si verifichi un danneggiamento dello stack che 'CVF' non sta catturando e in qualche modo ci soffia sopra. Nel codice c'è molto da fare visto che molti sviluppatori l'hanno toccato dagli anni '80 quando è stato scritto per la prima volta. – ja72

risposta

2

Stai girando il messenger. Il codice generato da Compaq anche chiama _chkstk(), la differenza è che lo ha sottolineato. Un'ottimizzazione comune. La differenza fondamentale tra i due frammenti è:

mov eax, 0D3668h 

vs

sub esp, 233E4h 

I valori che vedi qui utilizzato sono la quantità di spazio dello stack richiesto dalla funzione. Il codice Intel richiede 0xd3668 byte = 865869 byte.Il codice Compaq richiede 0x233e4 = 144356. Grande differenza. In entrambi i casi è piuttosto una grande quantità, ma quella Intel sta diventando critica, normalmente un programma ha uno stack di un megabyte. Inghiottire fino a 0,86 megabyte di esso lo sta spingendo molto vicino, annidare un paio di chiamate di funzioni e stai guardando il nome di questo sito.

Quello che devi scoprire, non posso aiutarti perché non è nel tuo snippet, è il motivo per cui la funzione generata da Intel ha bisogno di così tanto spazio per le sue variabili locali. I workaround sono di utilizzare il negozio gratuito per trovare spazio per i grandi array. Oppure usa l'opzione/STACK del linker per chiedere più spazio nello stack (indovinando il nome dell'opzione).

+0

Grazie per le informazioni. Puoi approfondire _use il negozio gratuito_ per trovare lo spazio? Ci sono molti calcoli che avvengono in questo array, riempiendo una serie di 18.000.000 di elementi di REAL * 8'. – ja72

+1

Sono piuttosto vecchio ma non abbastanza vecchio. Guarda le istruzioni ALLOCATE e DEALLOCATE nel tuo riferimento Fortran preferito. –

+0

Questi array sono allocati in VBA e passati a Fortran '.dll'. Non sono allocati in Fortran, quindi non posso usare matrici allocabili. Il post è stato molto utile, dato che sto ancora cercando una risposta qui. – ja72