Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stack overflow on subroutine call only when compiled with Intel Visual Fortran and fine when compiled by Compaq Visual Fortran

Using identical source files for a Fortran .dll I can compile them with Compaq Visual Fortran 6.6C or Intel Visual Fortran 12.1.3.300 (IA-32). The problem is that the execution fails on the Intel binary, but works well with Compaq. I am compiling 32-bit on a Windows 7 64-bit system. The .dll calling driver is written in C#.

The failure message comes from the dreaded _chkstk() call when an internal subroutine is called (called from the .dll entry routine). (SO answer on chkstk())

The procedure in question is declared as (pardon the fixed file format)

  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

and called like this:

      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)

with similar variable specifications except for crpm, qeff, rev and qqmax are arrays of which only the i-th elements is used for each SRF() call.

I understand possible stack issues if the arguments are more than 8kb in size, but in this case we have 7 x real(64) + 11 x int(32) + 2 x 2 x char(8) = 832 bits only in passed arguments.

I have worked really hard to move arguments (especially arrays) into a module, but I keep getting the same error

error.

The dissasembly from the Intel .dll is

intel

The dissasembly from the Compaq .dll is

compaq

Can anyone offer any suggestions on what is causing the SO, or how to debug it?

PS. I have increased the reserved stack space to hundreds of Mb and the problem persists. I have tried skipping the chkstk() call in the dissasembler but in crashes the program. The stack check starts from address 0x354000 and iterates down to 0x2D2000 where it crashes accessing a guard page. The stack bottom address is 0x282000.

like image 743
John Alexiou Avatar asked Apr 13 '12 19:04

John Alexiou


1 Answers

You are shooting the messenger. The Compaq generated code also calls _chkstk(), the difference is that it inlined it. A common optimization. The key difference between the two snippets is:

 mov eax, 0D3668h

vs

 sub esp, 233E4h

The values you see used here are the amount of stack space required by the function. The Intel code requires 0xd3668 bytes = 865869 bytes. The Compaq code requires 0x233e4 = 144356. Big difference. In both cases that's rather a large amount but the Intel one is getting critical, a program normally has a one megabyte stack. Gobbling up 0.86 megabytes of it is pushing it very close, nest a couple of functions calls and you're looking at this site's name.

What you need to find out, I can't help because it is not in your snippet, is why the Intel generated function needs so much space for its local variables. Workarounds are to use the free store to find space for large arrays. Or use the linker's /STACK option to ask for more stack space (guessing at the option name).

like image 181
Hans Passant Avatar answered Oct 02 '22 19:10

Hans Passant