Stack overflow because of too many functions?

Stack overflow because of too many functions?

Hi there,

I know this is not directlya fortran problem, but maybe someone with a greater programming experience can help me here...

Iwrote asimulation of an industrial furnace system inQuickWin.In the future, this program willrun at a real furnace for temperature calculations etc.

Because the QuickWin UI is not very modern, I should give it a face lift. So I did the following:
- I divided the QuickWin UI as a main program and the calculation kernel as a DLL
- The new GUI will be implemented with WPF and uses the calculation DLL

So I thought about the data exchange. Because the calculation DLL has to be in a seperate software evironment where CORBA is being used, I chose CORBA to avoid work in the future.

I wrote a C++ lib which provides a CORBA Server (mico to be precise). This lib is being linked to the calculation DLL, the CORBA idl files are being imported to WPF by IIOP.net. I tested how to exchange float values, characters, type fields, multidimensional arrays... All worked fine.

And now comes my problem:
I wrote a converter, that coded an interface for every variable we have in our module, which both the UI and the calculation DLL uses. When I called from WPF any interfacefunction, I get a stack overflow error.
Then I reduced the number of functions. At first, there were 558. When I reduce them to 130, it works fine.

I increased the stack size in my fortran calculation DLL to 2100000000 and /LARGEADDRESSAWARE (Support Addresses Larger Than 2 GB) as a linker option, but this didnt help. In my WPF project I cannot influence the stack size.

Has anybody an idea what this could be?

Thanks in advance,
Markus

10 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

Could you try /heap-arrays ?

No, /heap-arrays didnt do the trick.

The output window tells me:
First-chance exception at 0x10d56de7 (DFC_Kernel.dll) in DFC_GUI.exe: 0xC00000FD: Stack overflow.

DFC_Kernel.dll is my Fortran dll and DFC_GUI.exe the WPF GUI.

MICO, the CORBA server I use, is comfortable with such an amount of methods declared in the idl files.

I will code a few days on another project to get my head clean and then I will try again :-)

Markus

Merely having a large number of functions should not cause stack overflow. What matters is the call chain length. Is is possible that you have indirect recursion that has gone undetected?

A: ... call B;...
B: ... call C;...
.......
.......
P: ... call Q;...
Q: ... call B;... <<=== indirect recursion
R: ... call S;...

No, nothing like that. Here is one example:

Corba IDL File:

    void set_nBrammeGesamt(in long value);

    long get_nBrammeGesamt();
C++ Header:

    void set_nBrammeGesamt(CORBA::Long);

    CORBA::Long get_nBrammeGesamt();
C++ Code:

    extern "C" void FSET_NBRAMMEGESAMT(CORBA::Long*);

    void DataExchange_i::set_nBrammeGesamt(CORBA::Long value)

    {

        FSET_NBRAMMEGESAMT(&value);

    }

    extern "C" CORBA::Long FGET_NBRAMMEGESAMT();

    CORBA::Long DataExchange_i::get_nBrammeGesamt()

    {

        return FGET_NBRAMMEGESAMT();

    }
Fortran Code:

    subroutine FSET_NBRAMMEGESAMT(inValue)

    use Shared_Common !nBrammeGesamt is stored in that module

    implicit none

    INTEGER(KIND=4) inValue

    nBrammeGesamt = inValue

    return

    end subroutine FSET_NBRAMMEGESAMT
    integer(C_INT) function FGET_NBRAMMEGESAMT()

    use,intrinsic :: ISO_C_BINDING

    use Shared_Common

    implicit none

    FGET_NBRAMMEGESAMT = nBrammeGesamt

    return

    end function FGET_NBRAMMEGESAMT
I have 269 variables stored in shared_common, so there are 538 set/get methods declared in that way. There is no recursion in them, they just get or set a value in the module shared_common.

My next step would be to go around that problem by declaring a few type / structs to get or set a bunch variables to decrease the amount of methods.

Markus

>>I increased the stack size in my fortran calculation DLL to 2100000000 and /LARGEADDRESSAWARE (Support Addresses Larger Than 2 GB) as a linker option, but this didnt help

On Win32, Large Address is less than 3GB.
The DLL does not "declare" the stack size (unless it creates additional threads).
Increase the stack size on the app that calls the DLL (the DLL uses the caller's stack).

Do not set your app stack to 2100000000 as it might not run.
Use something reasonable 100000000 (100MB) assuming not-multi-threaded

If you still run outof stack space, verify that your C to F to C callingsequence agree (args and stack clean-up). When the calling conventions do not aggree, sometimes the calls "work", but the stack is not cleaned-up on the return. (IOW you lose stack on each call - without crash of app).

Jim Dempsey

www.quickthreadprogramming.com

Quoting onkelhotte

  1. subroutineFSET_NBRAMMEGESAMT(inValue)
  2. ..
  3. integer(C_INT)functionFGET_NBRAMMEGESAMT()

I don't think it will fix your problem, but you are missing BIND(C) clauses on those statements.

I tried it, but then I get linker errors, so I have to change something on the C++ side.
Although I cant use my character functions any more, because just 1 character is allowed then...

subroutine FSET_LAYOUTERRORSTRING(inValue) !bind(C)
use Shared_Common
implicit none
CHARACTER*20 inValue
layOutErrorString = inValue
return
end subroutine FSET_LAYOUTERRORSTRING

I will investigate it maybe later, but thanks for the advice. Maybe it helps.

Markus

Hi Jim,

my calling process isWPF, Im not sure how I can increase the stack size there. There are not many .NETproject settings (just "optimize","debug unmanaged code" and a few more).

I will investigate on the stack clean up maybe later today, but surely on monday.

Markus

PS: After I increased the stack and because it didnt work, I resetted it directly to a normal value, thanks for the hint.

Try BIND(C,NAME='FSET_LAYOUTERRORSTRING')

If you don't explicitly specify a binding label then it defaults to a lower case variant of the fortran procedure's name.

ifort (and other fortran compilers) pass an extra "hidden" argument for each character dummy argument for the length of the actual argument character variable. (BIND(C) suppresses that - hence the restriction on only passing length one character). Are you passing those hidden arguments out from your C++ side? Failure to do so could cause rather spectacular crashes. Consult the ifort docs about where the hidden arguments go in the calling sequence - it is compiler and compiler option specific.

(Note that putting in BIND(C) and having Fortran receive strings as character arrays is much more robust and portable, so much so that I personally wouldn't even contemplate not using that feature today for inter-language work.)

Leave a Comment

Please sign in to add a comment. Not a member? Join today