Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Beginner

Run time check failure

Sorry to ask yet another question!

I have a routine in Fortran that has been compile as CVF (as the version of NAG requires the CVF calling convention) below:

	LOGICAL*4 FUNCTION set_process_name (name, len1)
      !DEC$ATTRIBUTES ALIAS : '_SET_PROCESS_NAME@8' :: set_process_name

	IMPLICIT NONE
	CHARACTER	name*32
        INTEGER*4 len1, len2
      
	INTEGER*4	i

	LOGICAL*4	fin

	ProcessName = "                                "
	fin         = .FALSE.

	DO i = 1, 32
		IF ((Name(i:i) .GT. ACHAR(0)) .AND. (fin .EQ. .FALSE.)) THEN
			ProcessName(i:i) = Name(i:i)
		ELSE
			fin=.TRUE.
		END IF
	END DO

	set_process_name = .TRUE.

	RETURN
	END

The Fortran settings are

/nologo /debug:full /Od /I"Debug/" /I"..\Incl/" /I"C:\build\Intel Fortran RTO+ Calculation Engine\Sources\Solve\Debug/" /reentrancy:threaded /extend_source:132 /fpscomp:nolibs /debug-parameters:used /warn:declarations /warn:ignore_loc /fpe:1 /fp:source /names:uppercase /iface:cvf /module:"Debug/" /object:"Debug/" /Fd"Debug\vc140.pdb" /traceback /check:stack /libs:dll /threads /dbglibs /winapp /c

This Fortran routine called by a routine that is located inside an C++ MFC OLE Server compiled using stdcall as the default calling convention.

BOOL Application::SetProcessName(LPCTSTR p_Name)
{
	long lDum = 0;
	TRY
	{
		if (strncmp(p_Name, "###", 3) == 0)
		{
			LPCTSTR m_Name;
			m_Name = &p_Name[3];
			MonitorServer = (char *) malloc (strlen(m_Name) + 1);
			strcpy (MonitorServer, m_Name);
		}
		else
		{
			if (ProcessName == NULL)
			{
				free (ProcessName);
			}

			ProcessName = (char *) malloc (strlen(p_Name) + 1);

			// -----------------------------------
			// Set the process name in the fortran
			// -----------------------------------

			SET_PROCESS_NAME(p_Name, &lDum);
			
			strcpy (ProcessName, p_Name);
		}
		return TRUE;
	}
	CATCH_ALL (e)
	{
		THROW_LAST();
	}
	END_CATCH_ALL

	return FALSE;
}

The settings for the C++ are

/FR".\Debug\" /GS- /analyze- /W3 /Gy /Zc:wchar_t- /I"..\HysysLink/" /I"..\DXSConnect/" /ZI /Gm /Od /Fd".\Debug\" /Zc:inline /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MT" /D "_VC80_UPGRADE=0x0600" /D "_MBCS" /errorReport:prompt /WX- /Zc:forScope /RTC1 /Gz /Oy- /MDd /Fa".\Debug\" /EHsc /nologo /Fo".\Debug\" /Fp".\Debug\RtoOle.pch" 

The Fortran routine is declared in C++ as 

extern "C" long __stdcall SET_PROCESS_NAME(LPCTSTR, long *);

After the ' return FALSE' line is executed the CheckESP raises an exception 'Run-time check failure 0 - T'.

The call stack is below

     RtoOle.exe!failwithmessage(void * retaddr, int crttype, int errnum, const char * msg)    C++
     RtoOle.exe!_RTC_Failure(void * retaddr, int errnum)    C++
     RtoOle.exe!_RTC_CheckEsp()    C++
>    RtoOle.exe!Application::SetProcessName(const char * p_Name) Line 5654    C++
     [External Code]    
     RtoOle.exe!WinMain(HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, char * lpCmdLine, int nCmdShow) Line 26    C++
     [External Code]    

I thought that setting the calling convention in C++ for the Fortran routine is all that is needed to ensure that the routine is called properly with the correct stack handling.

 

0 Kudos
3 Replies
Highlighted

You used __stdcall in the C++

You used __stdcall in the C++ routine. This is NOT the C++ default and you attempted to paper over it by explicitly specifying an alias to Fortran including the name decoration, without telling Fortran it was STDCALL. This corrupts the stack.  It worked in CVF because STDCALL was the CVF default, but it's not in Intel Fortran.

There are other problems. The NAME argument to the Fortran routine is type CHARACTER. This implies a hidden length argument that you didn't pass.

There are several ways to fix this, but the simplest seems to be:

  • Remove __stdcall from the C++ declaration
  • Remove the ATTRIBUTES directive you have in the Fortran routine
  • Add "!DEC$ ATTRIBUTES REFERENCE :: name" after the declaration of the NAME dummy argument.
Retired 12/31/2016
0 Kudos
Highlighted
Beginner

Paper over it, I like that!

Paper over it, I like that!

I previously, set the compiler options for the C++ to use __stdcall as the default, as a possible workaround to an issue I had calling a NAG routine so I would have to reset this to use cdecl to follow your suggestions. I'll give it a try.

 

 

0 Kudos
Highlighted

If you want to use __stdcall,

If you want to use __stdcall, replace the ATTRIBUTES directive for set_process_name with:

!DEC$ ATTRIBUTES CVF :: set_process_name

You still need ATTRIBUTES REFERENCE for the name argument.

In general, any time you put explicit decoration (especially the @n) in an ALIAS, that's a sign that you've made a mistake. We do offer a DECORATE attribute to let the compiler do the correct decoration for the platform and calling convention.

Retired 12/31/2016
0 Kudos