我正在尝试使用 f2py 在 3 维中运行一个简单的积分问题。
调用fortran代码的python代码如下:
#!/Library/Frameworks/EPD64.framework/Versions/Current/bin/python
import pymods as modules
import pygauleg as gauleg
import pyint as integrator
import pylab as pl
import sys
import math
import time
############################################
# main routine #############################
############################################
zero = 0.0
one = 1.0
pi = pl.pi
Nr = 10
Nt = 10
Np = 2*Nt
r0 = zero
rf = one
NNang = Nr*Nt*Np
print 'Nr Nt Np = ', Nr, Nt, Np
print 'NNang = ', NNang
print 'r0 rf = ', r0, rf
Nx = int(math.floor( (one*NNang)**(one/3.0) ))
Ny = int(math.floor( (one*NNang)**(one/3.0) ))
Nz = int(math.floor( (one*NNang)**(one/3.0) ))
Nx = int(pl.floor(float(Nx)*1.75))
Ny = int(pl.floor(float(Ny)*1.75))
Nz = int(pl.floor(float(Nz)*1.75))
NNxyz = Nx*Ny*Nz
print 'Nx Ny Nz = ', Nx, Ny, Nz
print 'NNxyz = ', NNxyz
xyz0 = -rf
xyzf = rf
t1 = time.time()
xt = pl.zeros(Nt)
wt = pl.zeros(Nt)
gauleg.gauleg(xt, wt, 0.0, pl.pi, Nt)
print 'outside of gauleg'
虽然 Fortran 子例程有点长,但它的重要部分是开头......
2 subroutine gauleg(x,w,x1,x2,n)
3 !Input: x1,x2,n
4 !Output: x,w
5 !implicit none
6 !integer, parameter :: ikind = selected_int_kind(25)
7 !integer, parameter :: rkind = selected_real_kind(15, 307)
8 !
9 !real(kind = rkind), parameter :: pi = 3.14159265358979323846d00
10 !real(kind = rkind), parameter :: one = 1.0d00
11 !real(kind = rkind), parameter :: zero = 0.0d00
12 use mod_gvars
13
14 real(kind = rkind) :: tol = 1d-15
15
17 integer :: n
18 !!!!!f2py intent(in) n
19 real(kind = rkind), dimension(n) :: x
20 real(kind = rkind), dimension(n) :: w
22 real :: x1, x2
23
24 real(kind = rkind) :: z1, z, xm, xl, pp, p3, p2, p1;
25
26 integer(kind = ikind) :: m
27 integer(kind = ikind) :: i,j
28 integer(kind = ikind) :: countmax, counter, max_counter, min_counter
29
30 integer(kind = ikind) :: tenth, hundredth, thousandth
31
32 print*, 'n = ', n
最后...
98
99 print*, 'returning'
100
101 end subroutine
子例程顶部的注释(第 5 - 11 行)是 Fortran 模块 mod_gvars
中存在的结构。似乎一切都按计划进行*直到*该子例程返回。这是输出:
Nr Nt Np = 10 10 20
NNang = 2000
r0 rf = 0.0 1.0
Nx Ny Nz = 21 21 21
NNxyz = 1728
n = 10
m = 5
returning
python(14167) malloc: *** error for object 0x1081f77a8: incorrect checksum for freed object - object was probably modified after being freed.
*** set a breakpoint in malloc_error_break to debug
Abort trap
看起来子例程仅在返回时才遇到问题。为什么会出现这种情况?
最佳答案
这种问题通常是由于 Python 中的引用计数错误而发生的,例如,如果 f2py 中存在错误,或者在 Fortran 中覆盖的内存多于 numpy 数组中分配的内存,则可能会发生这种情况。所有这些错误仅在 Fortran 子例程退出后随机出现,通常是在 Python 中释放一些内存时。
要调试此问题,请尝试打印进入 Fortran 的所有数组,即打印数组 x、w,以确保您可以访问其中的所有内存(测试 f2py 使用相同的类型和等等)。
确保在 Fortran 中使用边界检查(在 gfortran 中至少使用 -fbounds-check
,最好只是 -fcheck=all
来检查所有问题)。
您也可以在调试器或 valgrind 下运行它,它可能会告诉您问题出在哪里。
最后,我个人更喜欢直接使用 Cython 来包装 Fortran。然后,我可以轻松访问所有生成的文件,并使用 iso_c_binding
Fortran 模块,以便 Fortran 编译器检查所有类型在 Fortran 和 C (Python) 之间是否兼容,请参阅 here举个例子。
关于python - f2py 中的 malloc 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12309161/