System.OutOfMemoryException用于尾递归函数
我已经将有问题的代码隔离到了此函数(使用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 ->
()
在h1
5626
次迭代之后,我得到一个System.OutOfMemoryException
5626
。 但是我的系统内存消耗只有20 percent
。 (我有一个非常强大的16 GB机器。)
为什么上面的函数应该溢出栈? 它是不是递归地写尾?
在此先感谢您的帮助。
我不认为这是一个尾递归问题 - 如果是这样,你会得到一个StackOverflowException
而不是一个OutOfMemoryException
。 请注意,即使您的计算机中有16 GB的内存,程序执行的过程可能会限制为较小的内存量。 IIRC,对于.NET框架版本和操作系统版本的某些组合,它的容量是3GB - 这可以解释为什么当内存使用量达到20%时(16GB = 20GB的20%),进程崩溃。
我不知道它有多大帮助,但可以简化代码以避免创建一些不必要的序列:
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内存限制的详细信息:是否有单个.NET进程的内存限制
OutOfMemoryException
通常与您拥有的RAM数量无关。 你可以在〜3 GB之内得到它,这很可能是因为你的代码是以32位进程运行的。 但切换到64位只会解决你的问题,如果你真的需要那么多的内存和异常不是由一些错误引起的。
上一篇: System.OutOfMemoryException for a tail recursive function