Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
27105 Discussions

chkstk.asm not found when debugging the Fortran code in Visual Studio 2017

cxqi
Novice
1,392 Views

Hi,

I am having a problem with my Fortran code recently. I can compile the program with no error and no warning. However, it is frozen when I run the executable file. When I debug the program, it shows 'chkstk.asm not found'. I searched it online and someone said this bug was due to the stack overflow. It could be solved by increasing the stack size under properties options, i.e.,

PROJECT->Properties->Configuration Properties->Linker->System->Stack Reserve Size=4194304

I tried it but it did not work, even I increase the stack size to 10MB. Did anyone encounter this issue before and how did you solve the problem?

Here I attach the screenshot to show the details of my problem. I hope someone could help me with this issue.

Very much appreciate it!

problem1.PNG

problem2.PNG

Labels (2)
0 Kudos
1 Solution
Steve_Lionel
Black Belt Retired Employee
1,299 Views

After some correspondence, I now see that this was being built as a 64-bit application. In that case, all my remarks about calling conventions are irrelevant as there is only one convention on x64, C. 

I was sent the project and was able to build and run it. I don't get an error, but it does go into a compute-bound loop. That's as far as I will take it.

View solution in original post

9 Replies
Steve_Lionel
Black Belt Retired Employee
1,372 Views

That the .asm can't be found is something you can ignore. It would only be an issue if you wanted to debug that Microsoft-supplied source.

That you get an error here is not stack overflow but rather stack corruption. It is detecting that when you call some routine, the stack is not "popped" properly on return. The most common way this happens is if, in a 32-bit application, you call a STDCALL convention routine but the caller thinks it is the C convention, or vice-versa.

Look at the procedure call that happened last before the error was triggered. Make sure that the calling convention is properly declared.

cxqi
Novice
1,365 Views

Hi Steve,

Thanks for your kind reply. I double-check my code and find the point that triggers the error. It is weird as I did not do anything at this point and the code did work last week. I have other versions of this program and they have the same routines like this one. They work well at this point. I don't understand why it does not work. 

Regarding the calling convention, could you please explain a bit more? 

Thanks!

Steve_Lionel
Black Belt Retired Employee
1,356 Views

The thing about stack corruption is that it may not always show itself in an obvious manner.

For 32-bit Windows applications, there are two conventions for calling routines, differing in how they treat the space used for arguments pushed onto the stack.

When you call a routine, each argument gets pushed onto the stack (for Fortran this is usually the address of the argument). For example, a routine that has three arguments will have 12 bytes pushed onto the stack. By "pushed", I mean that the stack pointer register has four subtracted from it for each argument, and the argument placed in those positions.

After the call returns, the stack pointer needs to be restored to what it was before the call - this is called "popping the stack". There are two conventions for how this is done.

The "C" convention requires the calling procedure to add the appropriate value to the stack pointer register after the call returns. The compiler knows how much it pushed, so it can easily add this instruction. This is the default used by Intel Fortran and also for Microsoft and Intel C/C++ compilers.

The "STDCALL" convention requires that the called procedure pop the stack before returning. It does this using a variant of the RET (return) instruction that includes the number of bytes to pop. The advantage of this is that it saves an instruction. The disadvantage is that the caller had better pass that exact number of arguments or else the stack pointer will be restored incorrectly. As a way of protecting against errors here, the convention is that the global name for a STDCALL routine has an @n suffix, where n is the number of bytes to pop. For example, a routine FOO with two arguments would be  _FOO@8. (Leading underscore is a convention for external routines in 32-bit Windows applications.) The idea is that the linker will complain if you call the routine with the wrong number of arguments, since the names won't match. However, not everyone follows this convention. All Windows API routines use STDCALL, as does Visual BASIC.

So what happens if you get it wrong? If you call a "C" convention routine but the caller thinks it's "STDCALL", the stack pointer never gets adjusted after the call returns. Sometimes this is harmless, but it can lead to surprise wrong results or other errors, since variables are no longer where the compiler thinks they are.

If you call a STDCALL routine but think it is C, then the stack gets popped twice! This is more likely to lead to errors later.

The Intel compiler (as does Microsoft C++) has a "stack check" option, enabled by default in a debug configuration. This adds code before and after every call to make sure that the stack got popped correctly. If it finds that it didn't, you get a "stack check" error, which happens in a routine coded with file name chkstk.asm (assembler).

This type of error happens most often when calling a STDCALL library routine from Fortran, without declaring it as STDCALL. So.. What defines this routine just before the error? In which language is it built and how is the routine documented? How do you declare it in Fortran and do you use any compile options such as /iface that change calling conventions?

cxqi
Novice
1,342 Views

Hi Steve,

Thanks for your detailed explanation. Regarding your questions, here are my answers. I am new to memory allocation. I hope you can excuse me if I made mistake in the answer.

  1. I think I used the 'C' convention as I did not use the  _FOO@8 in my code.
  2. The error occurs when the program calls a subroutine. It is weird when the debug cursor gets into this routine. It should go down from the first line to the end. However, it goes back to the first line [SUBROUTINE XX(arg1, arg2, arg3...)] when the cursor is already in a location inside the routine.  When I click the 'Step into' arrow, it triggers the error.
  3. I build the program in visual studio 2017 with the Intel OneAPI platform. The program is a Fortran 90 based package. What do you mean the routine documentation?
  4. I declare the routine using the 'SUBROUTINE' keyword. I installed the MingW 6.3.0. I am assuming the program is compiled by gfortran.

Thanks!

Steve_Lionel
Black Belt Retired Employee
1,333 Views

You would not use the "decorated" name in your program - the compiler would add the leading underscore and trailing @n if it thought it was a STDCALL routine.

Is the subroutine you are calling one that you wrote yourself? Is it part of your project? Please zip the .vfproj file and attach the zip to a reply here. 

cxqi
Novice
1,318 Views

Hi Steve,

I send you an email.

Please check your mailbox.

Thanks.

Steve_Lionel
Black Belt Retired Employee
1,300 Views

After some correspondence, I now see that this was being built as a 64-bit application. In that case, all my remarks about calling conventions are irrelevant as there is only one convention on x64, C. 

I was sent the project and was able to build and run it. I don't get an error, but it does go into a compute-bound loop. That's as far as I will take it.

JohnNichols
Valued Contributor II
1,280 Views

The scary bit is this makes sense.

cxqi
Novice
1,231 Views

I forgot to follow up here. Sorry about that. I just installed the latest Intel oneAPI Basic and HPC toolkit as suggested by Steve. It works well and I don't have this problem anymore.

Thanks for the help from Steve.

Reply