Fortran77代码触发Segmentation Fault(内存访问问题)求助
Fortran77 段错误(Segmentation Fault)排查分析
终端报错信息
Program received signal SIGSEGV, Segmentation fault. 0x0000000000f523b7 in bcvnmtn (xb=<error reading variable: Cannot access memory at address 0xc44a8000c3818>, yb=<error reading variable: Cannot access memory at address 0xc5dc8000c5138>, nstp=0, npoints=0, tx=..., ty=..., anx=..., any=...) at ./bcvnmtn.F:14 14 tx(1) = xb(1+nstp) - xb(1)
触发段错误的子例程 bcvnmtn
subroutine bcvnmtn(xb,yb,nstp,npoints,tx,ty,anx,any) c-----compute the vertex valued tangential and normal vector fields c----- (tx,ty)(n) and (anx,any)(n) to the curve (xb,yb)((n-1)*nstp+1) c----- for n=1 to npoints cdir$ nolist include 'paramcom.h' cdir$ list dimension xb(1),yb(1),tx(1),ty(1),anx(1),any(1) c-----get tangent vector field tx(1) = xb(1+nstp) - xb(1) ty(1) = yb(1+nstp) - yb(1) in = 1 do 100 n=2,npoints-1 inp = in + 2*nstp tx(n) = (xb(inp) - xb(in))*0.5 ty(n) = (yb(inp) - yb(in))*0.5 in = in + nstp 100 continue nlast = npoints ilast = 1 + (npoints-1)*nstp tx(nlast) = xb(ilast) - xb(ilast-nstp) ty(nlast) = yb(ilast) - yb(ilast-nstp) c-----normalize to unit length and rotate to get normal vector do 200 n=1,npoints tl = sqrt( tx(n)**2 + ty(n)**2 ) tx(n) = tx(n) / ( tl + tiny ) ty(n) = ty(n) / ( tl + tiny ) any(n) = tx(n) anx(n) = -ty(n) 200 continue return end
调用 bcvnmtn 的子例程 bcsymgd
subroutine bcsymgd(xi,yi) c-----compute ghost point locations along a symmetry boundary cdir$ nolist include 'common.h' include 'inputcom.h' include 'pointer.h' cdir$ list common /bcpoint/ idimfrm,jdimfrm,isttfrm,jsttfrm,nstpfrm,nofffrm, % idimtoo,jdimtoo,istttoo,jstttoo,nstptoo,nofftoo, % npoints dimension xi(0:idimfrm,0:jdimfrm),yi(0:idimfrm,0:jdimfrm) call bcvnmtn(xi(isttfrm,jsttfrm),yi(isttfrm,jsttfrm), % nstpfrm,npoints,tangx,tangy,anormx,anormy) call bcdifvf(dispx(isttfrm,jsttfrm),dispy(isttfrm,jsttfrm), % nofffrm,nstpfrm, % xi(isttfrm,jsttfrm),yi(isttfrm,jsttfrm), % (- nofftoo),nstpfrm, % xi(isttfrm,jsttfrm),yi(isttfrm,jsttfrm), % nofffrm,nstpfrm,npoints) call bctrflc(dispx(isttfrm,jsttfrm),dispy(isttfrm,jsttfrm), % dispx(isttfrm,jsttfrm),dispy(isttfrm,jsttfrm), % nstpfrm,npoints,tangx,tangy,anormx,anormy) call bcaddvf(xi(istttoo,jstttoo),yi(istttoo,jstttoo), % nofftoo,nstptoo, % dispx(isttfrm,jsttfrm),dispy(isttfrm,jsttfrm), % nofffrm,nstpfrm, % xi(isttfrm,jsttfrm),yi(isttfrm,jsttfrm), % nofffrm,nstpfrm,npoints) return end
问题背景
bcsymgd中的xi和yi为二维几何坐标数组,调用bcvnmtn时转换为一维数组xb、yb传入- 使用编译器:pgi/2020.4
- 代码为老旧大型程序,修改权限有限
错误原因分析
从报错信息可见核心异常:
nstp=0、npoints=0,直接导致子例程内数组访问逻辑完全失效,例如第14行的xb(1+nstp)虽未越界,但后续循环和末尾的数组索引计算会出现非法内存访问xb和yb无法读取内存,说明传入的数组指针无效,大概率是isttfrm、jsttfrm超出xi、yi的数组范围,或nstpfrm、npoints未正确初始化
排查建议
- 检查公共块参数初始化:确认
/bcpoint/公共块中的nstpfrm、npoints、isttfrm、jsttfrm在调用bcsymgd前已正确赋值,尤其npoints和nstpfrm不能为0 - 验证数组边界:检查
xi(isttfrm,jsttfrm)的索引是否在xi的有效范围(0:idimfrm, 0:jdimfrm)内,索引越界会传入无效指针 - 开启编译边界检查:用PGI编译器的
-C(数组边界检查)和-g(调试信息)选项重新编译,获取更详细的越界位置:pgf77 -g -C your_program.f -o your_program - 调试跟踪参数值:用GDB在
bcsymgd入口设断点,查看公共块参数实际值:gdb ./your_program break bcsymgd run print idimfrm, jdimfrm, isttfrm, jsttfrm, nstpfrm, npoints - 检查输出数组维度:确认
tangx、tangy、anormx、anormy的维度至少为npoints,避免写入越界
内容的提问来源于stack exchange,提问作者Surya Sarvajith
相关产品推荐
相关产品推荐

