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

debugging access violation on exit in mixed Fortran/C code

esatel
Beginner
1,948 Views

Hi,

I am working on a legacy mixed Visual Studio C/C++ and Intel Fortran simulation code using Intel compilers through visual studio on windows. The code entry and exit points are in Fortran. I use HDF5, my own C++ libraries and an antiquated C sparse matrix solver.

On success, the code does some clean up and calls "stop 0". The code seems to produce correct output, but routinely hangs in the exit statement with an "access violation". The problem is given in the debugger as:

HEAP[hydro.exe]: HEAP: Free Heap block 8c14bf8 modified at 8c14d48 after it was freed

Basically, the exit is the second freeing of memory. Commenting out the cleanup code in the C sparse matrix solver helps the program exit without "access violation" warnings. The data being accessed is not from the sparse solver, so I think the solver is overreaching.

Can someone explain how can I debug to test this theory, hopefully in the viz studio debugger? Can I set a watch on the heap block address? Is the mixed language programming going to kill me?

Thanks,

Eli

0 Kudos
5 Replies
SergeyKostrov
Valued Contributor II
1,948 Views
Hi, Please take a look at my comments...

Quoting esatel

...HEAP[hydro.exe]: HEAP: Free Heap block 8c14bf8 modified at 8c14d48 after it was freed

Basically, the exit is the second freeing of memory. Commenting out the cleanup code in the C sparse matrix solver helps
the program exit without "access violation" warnings...

[SergeyK] It looks like the C sparse matrix solver tries to release some memory that
was already releasedin another module.

The data being accessed is not from the sparse solver, so I think the solver is overreaching.

[SergeyK]The"Access Violation" exception is a logical outcome of some memory problems ( see above ).

Can someone explain how can I debug to test this theory, hopefully in the viz studio debugger?

[SergeyK] Two steps could be done forthe C sparse matrix solver codes:

- A C/C++Test-Case for the C sparse matrix solver
- In aDebug configuration you could enable MFC-based Memory Leaks detection.
Remember, that it willalsoallow to detect different memory management problems
includingBuffer Overrun cases. Please take a look at aPost #10 ina thread:

http://software.intel.com/en-us/forums/showthread.php?t=105227&o=a&s=lr


Could you create and posta C/C++ Test-Case for the C sparse matrix solver?

I don't doFortran programming so farbut I'll be able to help with C/C++.

Best regards,
Sergey

0 Kudos
esatel
Beginner
1,948 Views

Thanks Sergey.

It may be the leak detection is a good tool to start. I do not have an independent test case for the solver yet and the issue may well have to do with the context.

Can I use the MFC stuff in context of a mixed application that starts in Fortran? Enabling memory detection seems to involve adding certain defines or headers. What should I do -- call a C function right at the beginning of the fortran program that has the necessary includes?

The order may be subtly different than you describe, and this is what makes it hard to debug:

1. First the Sparse solver incorrectly frees memory

2. Second, the "legitimate" memory release occurs on exit(0) or "stop 0"

Most of the diagnostics go off during (2), which is probably not the problem code. The only useful diagnostic I have is the contended heap block address, but once I have that I need to rerun the code and find the other time the block is allocated.

Anyhow, this being a Fortran forum the most legitimate question I probably have for the group is the mixed language debugging question... either how to use the leak detection in a mixed environment or how to set a debugging watch using a heap address.

Thanks!

Eli

0 Kudos
IanH
Honored Contributor III
1,948 Views
(Check that all components are using the same C runtime library settings (which should be a debugging runtime for ... debugging) so that they are all using the same C runtime instance. If your program has DLL's they should be using the DLL variant of the runtime.)

You could call the _CrtDbg runtime support functions from Fortran. They are general Microsoft C runtime library support, not limited to MFC.

You probably need to write your own interface blocks for the routines based on inspection of crtdbg.h. For example:

[fortran] INTERFACE FUNCTION CrtCheckMemory() BIND(C,NAME='_CrtCheckMemory') USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_INT IMPLICIT NONE INTEGER(C_INT) :: CrtCheckMemory END FUNCTION CrtCheckMemory END INTERFACE IF (CrtCheckMemory() /= 0) THEN PRINT "('She''s all apples')" ELSE STOP 'Things have gone bananas!' END IF[/fortran]
If that's too fiddly then you could write some little C helper routines that called the debug routines, which your Fortran code could then call.

If you have control of the C code there's nothing stopping you from putting some before and after state checking code in there too. If you suspect the sparse solver that's probably the best starting point.

Note that I imagine that actions taken behind the scene by the Fortran runtime library might result in some noise.

If you know where the memory corruption is occurring (the symptoms you describe don't quite sound right for a "double-free") you could also set a data breakpoint on the address.
0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,948 Views
Quoting esatel
HEAP[hydro.exe]: HEAP: Free Heap block 8c14bf8 modified at 8c14d48 after it was freed

Such HEAP problems are typically a consequence of array out of bounds access in mixed-language or mixed-library environment. When the time comes to automatically release the memory at the end (either in C++ via destructors, or in Fortran via automatic dallocation), in the Debug configuration the RTL memory manager will check whether anyone has fiddled where it shouldn't have. However, you don't get an exception on that fiddling, but on the exit; it's not easy to find where the actual violation occur.

For example, a few days ago I resolved a similar problem. The culprit was like:

[fortran]use lapack90 real:: A(10,10) integer, allocatable:: ipiv(:)
...
allocate(ipiv(4))
call getrf(A, ipiv)[/fortran] Getrf is library routine which does factorization of A; ipiv should be at least 10 items long. However, it was shorter than required, and Getrf silently overwrote whatever memory was behind ipiv, and it was a completely unrelated vector, whose deallocation produced a HEAP error.

If you're lucky enough that the 0x8c14d48 address is consistent every time, you can:

  • Open a "Memory" debugger window, and type 0x8c14d48 to see the memory around
  • Step/run to cursor through the program, in smaller or greater steps
  • Spot when the address changes, and it shouldn't (the values will turn red)

Watch the LOCs of suspicious variables, it usually takes several attempts and debugging cycles to find the culprit.

Judging on the error message, you had a write into a dangling pointer (the vector was first freed, and after that written into).

Good luck

0 Kudos
SergeyKostrov
Valued Contributor II
1,948 Views
Quoting esatel
...
Can I use the MFC stuff in context of a mixed application that starts in Fortran? Enabling memory detection
seems to involve adding certain defines or headers. What should I do -- call a C function right at the
beginning of the fortran program that has the necessary includes?...

Here is a consolidation of codes you could use:

[cpp] // Header files ... #define CRTDBG_MAP_ALLOC #include #include ... // Initialization ... TCHAR *g_pszMemLeaksReportLog = _T("C:\MemLeaksReport.log"); ... HANDLE hLogFile = NULL; _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_DEBUG ); hLogFile = ::CreateFile( g_pszMemLeaksReportLog, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); if( hLogFile == NULL ) return; _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE ); _CrtSetReportFile( _CRT_WARN, hLogFile ); _RPT0( _CRT_WARN, "Processing Startedn" ); ... // Your processing... // Final cleanups ... _CrtDumpMemoryLeaks(); _RPT0( _CRT_WARN, "Processing Completedn" ); if( hLogFile != NULL ) { ::CloseHandle( hLogFile ); hLogFile = NULL; } ...[/cpp]

These libraries should be used ( Debug versions ):

msvcrtd.lib
msvcurtd.lib if Unicode Character Set is used

Best regards,
Sergey
0 Kudos
Reply