Fortran中发生意外的“内存分配失败”异常,只有很少的内存分配请求

时间:2019-03-26 13:46:31

标签: memory fortran windows-10

当我只需要大约100 real(8)的内存时,就会发生Fortran运行时错误“内存分配失败”。

我正在用Fortran编写一些代码。我使用了几个(大约十个)可分配的real(8)数组。分配它们时,命令行显示“内存分配失败”。但是我只将它们的大小分配给大约十。我已经对计算机进行了简要检查,但我认为计算机无法处理100个浮点数。

代码是这样的:

module m
contains

function foo (a, b, c) result (...)
implicit none
  real(8), allocatable, intent(inout) :: a(:), b(:), c(:)
  allocate(a(0:10)) ! Actual size include an integer n passed to here. I'm pretty sure n is no greater then 10
  allocate(b(1:10))
  allocate(c(0:9))
  ! Some calculation
  a_variable = bar(...)
endfunction foo 

function bar (...) result (x)
implicit none
  real(8), allocatable :: x(:)
  allocate(x(8)) ! This is line X
  ! Some calculation
endfunction bar

endmodule m

program testm
use m
implicit none
  ! Some code that calls foo
endprogram testm

当我编译并运行代码时,命令行会告诉我“内存分配失败”,并显示来自操作系统的错误消息(Windows 10)“内存资源不足,无法完成此命令”。这真的很奇怪,因为我只要求大约100个浮点数的内存。

当我尝试确保我没有意外地将大量数字传递给n时,甚至会更加令人困惑。

当我在X行中添加print*, n时,异常仍然存在,并且指示的行仍然是X行,即现在的print代码!

我完全不知道这可能是哪种错误。由于我是Fortran的初学者,所以不确定在这里是否进行了任何未定义的行为。

我正在使用g95在Windows 10上编译.f90文件。

这是完整的代码:

module SplineInterp
! MODULE COMMENT
! Cubic Spline Interpolation Module
! Does Cubic Spline Interpolation with natural boundary conditions
! All calculation is made in real(8). Parameter rk = 8 is defined for real kind specifications.
! In all places where an unexpected zero on the denominator appears, the program will stop with a message,
!  usually "The matrix is singular!". A number n is considered to be zero if dabs(n) < e_min, e_min is a
!  pre-defined parameter.

integer, parameter :: rk = 8
real(rk), parameter :: e_min = 1d-5

contains

function CH_SOLVE (a, b, c, f, n) result (x)
implicit none
! FUNCTION COMMENT
! Thomas Chasing Method, solves a tri-diagonal-matrix linear equation set Ax=f
! First does LU-decomposition and then solves the upper- and lower-triangular equations
! ARGUMENTS:
!   a(2:n), b(1:n), c(1:n-1) :: elements of the coefficient matrix A. See lecture notes for convention
!   f(1:n) :: the inhomogeneous term column-vector in the equation
!   n :: size of coefficient matrix
! RETURNS:
!   x :: solution to the equation

    real(rk), allocatable, intent(inout) :: a(:)
    real(rk), allocatable, intent(inout) :: b(:)
    real(rk), allocatable, intent(in) :: c(:)
    real(rk), allocatable, intent(inout) :: f(:)
    integer, intent(in) :: n
    ! Iteration variable
    integer :: i
    real(rk), allocatable :: x(:)
    print*, n
    allocate(x(n))
    ! LU-decomposition
    ! because L has only one non-trivial diagonal line, we can multiply L^-1 to f during the process
    ! See lecture notes for formulae used
    do i = 2, n
        if (dabs(b(i - 1)) < e_min) then
            stop "The matrix is singular!"
        endif
        ! Calculate elements of L
        a(i) = a(i) / b(i - 1)
        ! Calculate elements of U
        b(i) = b(i) - a(i) * c(i - 1)
        ! Multiply L^-1 to f
        f(i) = f(i) - a(i) * f(i - 1)
    enddo
    if (dabs(b(n)) < e_min) then
        stop "The matrix is singular!"
    endif
    ! Solve Ux=(L^-1 f) using front-iteration method
    ! See lecture notes for formulae used
    x(n) = f(n) / b(n)
    do i = n - 1, 1, -1
        if (dabs(b(i)) < e_min) then
            stop "The matrix is singular!"
        endif
        x(i) = (f(i) - c(i) * x(i + 1)) / b(i)
    enddo

endfunction CH_SOLVE

function interp (x, y, n, xi) result (yi)
implicit none
! FUNCTION COMMENT
! Interpolates the values of y at points xi based on the given data points (x, y)
! Using Cubic-Spline Interpolation, solving the intermediate equation set with Thomas Method
! ARGUMENTS:
!   x, y :: Known data points, should be one-dimensional arrays of same shape (0:n)
!   n :: size of given datas points
!   xi :: The points at which the interpolation is to be evaluated (assumed to be in increasing order)
! RETURNS:
!   yi :: Interpolation results, an array with the same size of xi

    real(rk), allocatable, intent(in) :: x(:), y(:), xi(:)
    integer, intent(in) :: n
    real(rk), allocatable :: yi(:)
    ! Intermediate variables
    ! h(0:n-1) :: length of intervals
    ! M(0:n) :: to be solved, second-order-derivatives of spline function at data points
    ! mu(2:n-1), l(1:n-2), diag2(1:n-1) :: coefficients in the tri-diagonal-matrix
    ! d(1:n-1) :: non-homogeneous term in the linear equation set
    real(rk), allocatable :: h(:), M(:), mu(:), l(:), diag2(:), d(:)
    ! Iteration variable
    integer :: i, j
    print*, n
    allocate(yi(size(xi)))
    allocate(h(0 : n-1))
    allocate(M(0 : n))
    allocate(mu(2 : n-1))
    allocate(l(1 : n-2))
    allocate(diag2(1 : n-1))
    allocate(d(1 : n-1))
    ! Construction of linear equation set for M
    ! Calculation of h, m & d, see lecture notes for formulae used
    h(1) = x(2) - x(1)
    do i = 2, n-1
        h(i) = x(i + 1) - x(i)
        ! Used a trick here, calculate d(i) in two parts to save calculation time
        d(i+1) = - (y(i + 1) - y(i)) / h(i)
        d(i) = (d(i) - d(i + 1)) * 6 / (h(i - 1) + h(i))
        mu(i) = h(i - 1) / (h(i - 1) + h(i))
        if (i <= n-2) then
            l(i) = h(i) / (h(i - 1) + h(i))
        endif
    enddo
    ! Do Thomas Method solving
    diag2 = 2 ! Diagonal elements of coefficient matrix are all 2
    M(1 : n - 1) = CH_SOLVE(mu, diag2, l, d, n-1)
    ! Boundary conditions
    M(0) = 0
    M(n) = 0
    ! Do evaluation
    ! Here j represents the index of interval where the current xi points is
    j = 0
    ! Interpolation point is invalid if it's smaller than the smallest x
    if (xi(1) < x(0) - e_min) then
        stop "Invalid interpolation point!"
    endif
    do i = 1, size(xi)
        ! Locate the interval where xi(i) is
        do while (xi(i) > x(j + 1) + e_min)
            j = j + 1
            ! Invalid interpolation point if xi(i) > x(n)
            if (j >= n) then
                stop "Invalid interpolation point!"
            endif
        enddo
        ! See lecture notes for this formula
        yi(i) = (x(j+1)-xi(i))**3*M(j)/(6*h(j))&
                +(xi(i)-x(j))**3*M(j+1)/(6*h(j))&
                +(y(j)-M(j)*h(j)**2/6)*(x(j+1)-xi(i))/h(j)&
                +(y(j+1)-M(j+1)*h(j)**2/6)*(xi(i)-x(j))/h(j)
    enddo

endfunction interp

endmodule SplineInterp

program DoSplineInterp
use SplineInterp
implicit none
! PROGRAM COMMENT
! A program to use to above algorithm to interpole the profile of an airplane wing

    real(rk), allocatable :: x(:), y(:), xi(:), yi(:)
    ! Iteration variable
    integer :: i
    integer, parameter :: n = 9
    allocate(x(0:9))
    allocate(y(0:9))
    allocate(xi(151))
    allocate(yi(151))
    x = (/0d0, 3d0, 5d0, 7d0, 9d0, 11d0, 12d0, 13d0, 14d0, 15d0/)
    y = (/0d0, 1.2d0, 1.7d0, 2d0, 2.1d0, 2d0, 1.8d0, 1.2d0, 1d0, 1.6d0/)
    ! xi are evenly-distributed points with interval 0.1 between 0 and 15
    do i = 1, 151
        xi(i) = (i - 1) * 0.1
    enddo
    yi = interp(x, y, n, xi)
    ! Write results to file
    open (1, file = "Spline.txt", status = "new")
    write (1, *) "x:"
    write (1, *) x
    write (1, *) "y:"
    write (1, *) y
    write (1, *) "xi:"
    write (1, *) xi
    write (1, *) "yi:"
    write (1, *) yi
    close(1)

endprogram DoSplineInterp

0 个答案:

没有答案