Fortran程序内存分配异常:malloc(): corrupted top size报错排查
Fortran局部密度程序内存崩溃问题分析与修复
问题成因
报错malloc(): corrupted top size是堆内存被非法写入破坏导致的,核心原因是数组下标越界访问:
- 当
n_grid=19、ds=3d0、L=59.99999d0时,ds*n_grid=57d0 < L,粒子坐标经过周期性边界条件处理后范围是[0, L)。当坐标接近L(比如59.99999)时,floor(rco/ds)=floor(59.99999/3)=19,加1后得到20,但dn数组的维度是(19,19,19),最大下标为19,此时写入dn(20,q,r)会直接越界,破坏堆内存的管理结构。 - 从运行输出能看到
sum(dn)=183355远小于n*nc=193536,说明大量粒子的索引越界,未被正确统计到dn数组中,同时非法写入了其他内存区域。 - 当
n_grid>=20时,ds*20=60d0 >= L,此时floor(L/ds)=19,加1后是20,刚好匹配dn数组的最大下标,不会越界,因此程序正常运行。
修复方案
针对索引越界问题,采用两种互补的修复手段:
- 正确计算n_grid:根据盒子尺寸L和网格步长ds,计算刚好能覆盖整个盒子的网格数,避免出现网格范围小于盒子的情况:
n_grid = ceiling(L / ds) ! 用天花板函数确保网格总长度>=L - 强制索引边界检查:对计算出的网格索引做模运算,确保其始终落在
1~n_grid范围内(即使出现浮点精度误差导致的超界):
注:由于坐标已通过周期性边界条件处理为p = mod(floor(rco(1, (i-1)*n + j)/ds), n_grid) + 1 q = mod(floor(rco(2, (i-1)*n + j)/ds), n_grid) + 1 r = mod(floor(rco(3, (i-1)*n + j)/ds), n_grid) + 1[0,L),floor(rco/ds)结果非负,模运算后范围为0~n_grid-1,加1后刚好是合法的数组下标。
修改后的完整代码
program localdensity implicit none integer :: i , j , k , a , b , n_grid , n , nc , p , q , r , ncin1 double precision :: L , ds , ignore double precision, allocatable :: dn(:,:,:) double precision, allocatable :: rco(:,:) ! INPUT PARAMETERS ! ncin1 = 14 ! total configurations in each block file nc = ncin1*1 ! total block files ds = 3d0 ! dx = dy = dz = 2 A ! INPUT PARAMETERS ! print*, 'started reading data file' open (1, file = 'Silica_13824_negative_press-11_100.txt', status = 'old') read(1,*) n , ignore , L close(1) print* , n , L L = 59.99999d0 !L = 60.0001d0 allocate(rco(3,nc*n)) ! 修复:正确计算n_grid,确保覆盖整个盒子 n_grid = ceiling(L / ds) print*, 'calculated n_grid: ', n_grid allocate(dn(n_grid , n_grid , n_grid)) open (1, file = 'Silica_13824_negative_press-11_100.txt', status = 'old') do j = 1 , nc read(1,*) do i=1,n k=i+(j-1)*n read(1,*) a , b , rco(1,k), rco(2,k), rco(3,k) ! reading data (x,y,z) end do end do print*, 'ended reading data file n :' , n , L close(1) rco(:,:) = rco(:,:) - L*floor(rco(:,:)/L) ! Appying Periodic Boundary condition dn = 0 print* do i = 1,nc do j = 1,n ! 修复:用模运算确保索引在合法范围内 p = mod(floor(rco(1 , (i-1)*n + j) / ds), n_grid) + 1 q = mod(floor(rco(2 , (i-1)*n + j) / ds), n_grid) + 1 r = mod(floor(rco(3 , (i-1)*n + j) / ds), n_grid) + 1 dn(p,q,r) = dn(p,q,r) + 1 end do if (mod(i,ncin1)==0) print*, 'block', i/ncin1, 'done' end do print*, 'total particles counted :', sum(dn) ,'; n*nc = ', n*nc print*, 'nc is ' , nc dn = dn/nc print*, sum(dn) print*,'n_grid' ,n_grid open (unit = 2, file = "parameters_neg.txt" , action="write" , status="replace") write(2,*) n , nc , L , n_grid close(2) open (unit = 3, file = "data_from_program_neg.txt" , action="write" , status="replace") do i = 1 , n_grid do j = 1 , n_grid do k = 1 , n_grid write(3,*) i , j , k , dn(i,j,k) end do end do end do close(3) print*, 'Program has computed everything, data has been saved to data_from_program.txt. Now run file named local_density.py ' endprogram localdensity
内容的提问来源于stack exchange,提问作者Mayank Sharma
相关产品推荐
相关产品推荐

