Racket中custodian-limit-memory未触发内存不足错误?
问题原因
你当前的代码只是通过parameterize临时切换了current-custodian参数,但运行代码的当前线程仍然属于顶级custodian(程序启动时默认的custodian)。Racket中,对象的内存归属由创建它的线程所属的custodian决定,而非当前current-custodian参数的值。因此你设置的2MB内存限制根本没有作用在make-bytes的内存分配上,自然不会触发内存不足错误。
修正方案
要让custodian的内存限制生效,必须让内存分配操作在由该custodian管理的线程中执行。你需要创建一个新线程,并将该线程的归属custodian设置为你创建的带内存限制的custodian。
修正后的代码如下:
#lang racket/base (with-handlers ([exn:fail:out-of-memory? (λ (err) (println "Caught out-of-memory error! :D"))]) (let ([limit-custodian (make-custodian)]) ; 设置2MB内存限制 (custodian-limit-memory limit-custodian (* 2 1024 1024)) ; 创建由limit-custodian管理的线程 (define mem-hog-thread (thread (λ () ; 切换current-custodian,确保对象归属到目标custodian (parameterize ([current-custodian limit-custodian]) (make-bytes (* 4 1024 1024)))))) ; 等待线程执行,触发可能的异常 (sync mem-hog-thread) (println "Should have raised OoM. :(")))
补充说明
- 线程创建后必须用
sync等待执行结束,这样才能捕获到线程因内存限制被终止时抛出的异常。 parameterize ([current-custodian limit-custodian])确保线程内创建的对象归属到目标custodian,让内存限制能够正确统计这些对象的大小。- 当custodian管理的内存总和超过限制时,Racket会先尝试垃圾回收,若回收后仍超过限制,则会终止该custodian下的所有线程,并抛出
exn:fail:out-of-memory异常。
内容的提问来源于stack exchange,提问作者Cazra
相关产品推荐
相关产品推荐

