0

我遇到了变量被覆盖的问题,因为我不知道是什么原因。我在下面发布了一段代码,以便您可以看到事情是如何声明的。变量应变、Qi、Qf、Qd、tel 和 Gc 被传递到子程序并用于计算 ssgrad、strn0、strss0。

我的问题是 tel 和 Gc 被传递到子程序 OK 但由于某种原因在这段代码中更改了值。

使用打印语句,我发现问题首先出现在第二个 do 循环中。当我将 strss0 设置为 0 时,Gc 和 tel 的值从都等于 1 变为看似随机的数字:tel=11.52822 Gc=-8.789086 (仅为示例而显示)

每次我运行代码时,它们都会设置为相同的值。

只是让你知道,这个子程序与商业有限元包接口。

非常感谢您对此的任何帮助

subroutine initcalcs(strain,Qi,Qf,Qd,tel,Gc,ssgrad,strn0,strss0)

  implicit none

  integer :: i,j

  real*8:: nstrn0,nstrs0,strn0,strnf,varsq,normvar,lmbda0,lmbdaf,
 # ssgrad,t0,tt,tel,nstrnf,nstrsf,Gc

  real*8, dimension(3) :: strain,stran0,stranf,strss0,strssf,var

  real*8, dimension(3,3) :: Qd,Qi,Qf


  lmbda0=1.0d0                                                                                          


  nstrn0=0.0d0                                                                             
  do i=1,3
        stran0(i)=0.0d0
        stran0(i)=strain(i)*lmbda0                                                         
        nstrn0=nstrn0+stran0(i)**2                                                         
  end do                                                                                    

  nstrn0=dsqrt(nstrn0)                                                                     


  do i=1,3
        strss0(i)=0.0d0 
  end do
4

2 回答 2

3

在 Fortran 中,内存值损坏有两个常见原因。一种是下标错误,您使用不正确的下标值分配给数组元素。这将写入数组外部的内存位置。另一个是对过程(子例程或函数)的调用中的参数与过程的虚拟参数之间的分歧。两者都可能导致问题出现在与实际原因不同的源代码位置。建议:检查您的代码是否存在这些问题。打开编译器的严格警告和错误检查选项。Fortran >=90 和模块的使用使 Fortran 能够更好地自动查找参数一致性问题。您可以使用调试器监视内存位置并查看它修改了什么。

于 2013-06-13T00:26:45.880 回答
1

我同意 MSB:打开严格的警告和错误检查,并验证子例程调用传递的参数与子例程期望的类型和形状(数组维度)相同。

变量声明语法中的冒号暗示这是 Fortran90 或更高版本。如果是这种情况,我强烈建议使用INTENT修饰符来指定参数是否是只读的。

例如,假设传递给该例程的参数中,strainQiQfQdtelGc是只读输入,而参数是ssgradstrn0strss0作为输出返回;也就是说,它们的任何值都会被此例程覆盖。

参数的变量声明将更改为:

real*8, dimension(3), intent(in) :: strain
real*8, dimension(3,3), intent(in) :: Qi, Qf, Qd
real*8, intent(in) :: tel, Gc

real*8, intent(out) :: strn0, ssgrad 
real*8, dimension(3), intent(out) :: strss0

该关键字是对 Fortran 90 的补充,INTENT它允许用户指定哪些参数是只读的INTENT(IN)INTENT(INOUT)INTENT(OUT)

如果INTENT未指定,则默认与 FORTRAN 77 一致(请注意,与未指定INOUT之间存在细微差异,但在本示例中不相关)。INTENT(INOUT)INTENT

如果例程试图为声明的变量赋值,一个好的编译器会抛出错误,如果声明的变量没有被赋值INTENT(IN),至少会抛出警告。INTENT(OUT)

如果可能,设置INTENT(IN)所有应该是只读的变量。这可能是不可能的,这取决于这些变量如何传递给其他例程。如果INTENT未在此例程中调用的例程的参数上指定,则默认为INOUT. 如果将INTENT(IN)变量作为INTENT(INOUT)参数传递,编译器将抛出错误。如果这发生在您控制的代码中,您必须INTENT在许多例程中指定。这可能是可取的,也可能不是可取的,具体取决于您是要总体改进代码还是只是快速解决这个问题。

我假设其中一些变量被传递给有限元包中的外部例程,我猜这些变量是链接到您的代码而不是编译的;我不确定在这种情况下如何处理编译时意图检查。

于 2014-08-21T23:46:47.037 回答