我已将有问题的代码隔离到此函数(使用 ASP.NET 的 Membership 类):

let dbctx = DBSchema.GetDataContext() 
let rec h1 (is2_ : int) (ie2_ : int) : unit = 
    match is2_ >= ie2_ with 
    | true -> 
        let st2 = query { 
            for row in dbctx.Tbl_Students do 
            where (row.Id = is2_) 
            head} 
        let l2 = 
            Membership.FindUsersByEmail (st2.Email_address) 
            |> Seq.cast<_> 
            |> Seq.length 
        match l2 >= 1 with 
        | true ->  
            () 
        | false -> 
            Membership.CreateUser (st2.Email_address, password, st2.Email_address) 
            |> ignore 
        h1 (is2_ - 1) ie2_ 
    | false -> 
        () 

h15626 次迭代之后,我得到了一个 System.OutOfMemoryException。但我的系统内存消耗仅为 20%。 (我有一台非常强大的 16 GB 机器。)

为什么上面的函数会溢出栈?不是递归写tail吗?

预先感谢您的帮助。

请您参考如下方法:

我认为这不是尾递归问题——如果是这样,您将得到一个 StackOverflowException 而不是 OutOfMemoryException。请注意,即使您的机器中有 16GB 的内存,您的程序在其中执行的进程也可能仅限于较小的内存量。 IIRC,对于 .NET Framework 版本和操作系统版本的某些组合,它是 3GB——这可以解释为什么当您达到约 20% 的内存使用率(16GB 的 20% = 3.2GB)时进程崩溃。

我不知道它会有多大帮助,但您可以简化代码以避免创建一些不必要的序列:

let dbctx = DBSchema.GetDataContext() 
let rec h1 (is2_ : int) (ie2_ : int) : unit = 
    if is2_ >= ie2_ then 
        let st2 = query { 
            for row in dbctx.Tbl_Students do 
            where (row.Id = is2_) 
            head } 
        let existingUsers = Membership.FindUsersByEmail st2.Email_address 
        if existingUsers.Count < 1 then 
            Membership.CreateUser (st2.Email_address, password, st2.Email_address) 
            |> ignore 
 
        h1 (is2_ - 1) ie2_ 

编辑:这是指向上一个问题的链接,其中包含有关某些版本的 .NET 框架和操作系统版本的 CLR 内存限制的详细信息:Is there a memory limit for a single .NET process


评论关闭
IT序号网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!