- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have Fortran main program to call C function that retrun a dynamic array. In the C function, it uses malloc() to allocate the array. How Fortran can free the allocated array by C?
Thanks a lot!
Here is my Fortran program example:
Program main
USE ISO_C_BINDING
IMPLICIT NONE
! INTERFACE block must set up the interface between C and Fortran.
INTERFACE
SUBROUTINE c_sub(dim, W_ptr) BIND (C,NAME='c_sub')
USE ISO_C_BINDING
INTEGER (c_int) ::dim
type(c_ptr) :: W_ptr
!DEC$ ATTRIBUTES REFERENCE :: W_ptr ! necessary for the interface
END SUBROUTINE ExecuteMOR
END INTERFACE
! local variable
INTEGER :: dim, i
REAL*8, allocatable,DIMENSION(:) :: W
REAL*8, DIMENSION(:), pointer :: W_fptr
type (c_ptr) :: W_ptr
call c_sub(dim, W_ptr)
! convert c pointer to fortran pointer
CALL C_F_POINTER(W_ptr, W_fptr, dim)
! allocate W as new size
allocate(W(dim))
do i = 1, dim
W(i) = W_fptr(i)
end do
...
deallocate(W)
how to free memory W_ptr???
END program main
The C function is like that:
void c_sub(int *dim, double **W_ptr)
{
*dim = 5;
*W = (double *)malloc((*dim)*sizeof(double));
}
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I tried to pass W_ptr to another c function and free it. But it doesn't work.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You don't need the !DEC$ ATTRIBUTES REFERENCE in the interface body for c_sub. Reference is already the default for subroutines with the BIND attribute. To override the default you could give W_ptr the VALUE attribute, but you don't want to do that because you want to return a result through this dummy argument.
Passing W_ptr to another C function to free it should work if you get the level of indirection right as you did with your interface for c_sub. If you can't get it to work show the c function, the Fortran interface body, and the Fortran invocation.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
When you END the PROGRAM the Process terminates. Terminating the process returns the C heap regardless of any dangling allocations.
I suggest you consider adding a "c_sub_free" funciton to deallocate the C allocated memory when it is no longer needed. Note, at some point in the future you might want to use C++ with new/delete and non-default dtor.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi, Jim:
I followed your suggestion and created another C function to free memory. But it did not work. The program report accessing error during the free() in C function. Can you give me some suggestion? Here is fortran code
Program main
USE iso_c_binding
IMPLICIT NONE
! INTERFACE block must set up the interface between C and Fortran.
INTERFACE
SUBROUTINE c_sub(dim, W_ptr) BIND (C,NAME='c_sub')
USE ISO_C_BINDING
INTEGER (c_int) ::dim
type(c_ptr) :: W_ptr
END SUBROUTINE c_sub
SUBROUTINE c_subfree(dim, W_ptr) BIND (C,NAME='c_subfree')
USE ISO_C_BINDING
INTEGER (c_int) ::dim
type(c_ptr) :: W_ptr
END SUBROUTINE c_subfree
END INTERFACE
! local variable
INTEGER :: dim, i
REAL*8, allocatable,DIMENSION(:) :: W
REAL*8, DIMENSION(:), pointer :: W_fptr
type (c_ptr) :: W_ptr
call c_sub(dim, W_ptr)
! convert c pointer to fortran pointer
call c_f_pointer(W_ptr,W_fptr, [dim])
! allocate W as new size
allocate(W(dim))
do i = 1, dim
W(i) = W_fptr(i)
end do
deallocate(W)
call c_subfree(dim,W_ptr)
END program main
C code is:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
void c_sub(int *dim, double **W_ptr)
{
*dim = 5;
*W_ptr = (double *)malloc((*dim)*sizeof(double));
}
void c_subfree(int *dim, double **W_ptr)
{
free(*W_ptr);
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Well, I'm stumped. Your code looks fine to me and in fact runs to completion without error in gfortran/gcc.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
...and ifort (though I think the value of W_fptr is undefined, so the program is technically non-conforming)
[plain]>cl /c "2013-04-02 c.c" && ifort /check:all /warn:all /stand:f03 /standard-semantics "2013-04-02 fortran.f90" "2013-04-02 c.obj" && "2013-04-02 fortran.exe" && echo All done
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
2013-04-02 c.c
Intel(R) Visual Fortran Compiler XE for applications running on IA-32, Version 13.1.1.171 Build 20130313
Copyright (C) 1985-2013 Intel Corporation. All rights reserved.
2013-04-02 fortran.f90(23): warning #6916: Fortran 2003 does not allow this length specification. [8]
REAL*8, allocatable,DIMENSION(:) :: W
---------^
2013-04-02 fortran.f90(24): warning #6916: Fortran 2003 does not allow this length specification and using it in new code is silly, get out of the habit now. [8]
REAL*8, DIMENSION(:), pointer :: W_fptr
---------^
Microsoft (R) Incremental Linker Version 10.00.40219.01
Copyright (C) Microsoft Corporation. All rights reserved.
"-out:2013-04-02 fortran.exe"
-subsystem:console
"2013-04-02 fortran.obj"
"2013-04-02 c.obj"
All done
[/plain]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I used Intel fortran composer 2013 (64bit) and MS visual studio 2010. In fact, my C code was compiled as static library and then was linked to my Fortran code. In addition, my C code also linked some dll too. But my code is very similar to the test example as I posted. During the debuging, error reports when call the free() function as:
This may be due to a corruption of the heap, which indicates a bug in test.exe or any of the DLLs it has loaded.
This may also be due to the user pressing F12 while test.exe has focus.
In output windows it says:
HEAP[test.exe]: Invalid address specified to RtlValidateHeap( 0000000002360000, 000000000E71FDD0 )
Windows has triggered a breakpoint in test.exe.
The output window may have more diagnostic information
I am confused!! Thanks in advance for any suggestion.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Use "real(8)" not "real*8" top avoid the warning.
Using VS 2010 SP1Rel, Intel C++ 2011.9.300, and IVF 2011.10.325
All combinations of MSC++/ICC/IVF/32-bit/64-bit run to completion (at least for Debug build).
Note, I had an issue where the project did not rebuild the static lib when using MS C++. Had to clean after switching C++ compilers.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I finally figured out the problem. In my real code, the pointer created by malloc() was wrongly assigned to a pointer created by a dll. That's why I wasn't able to free it since the dll is finished. The example code, which I posted here, indeed works well.
Thank you guys very much!!

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page