You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

MemoryStack栈空间耗尽:如何正确使用LWJGL MemoryStack?

解决LWJGL MemoryStack与JOML配合的栈空间耗尽问题

错误原因

你遇到的「MemoryStack: Out of stack space」是因为全局持有MemoryStack实例,每次调用mallocFloat都会在同一个栈帧上持续分配内存,没有机会释放栈空间。MemoryStack是基于栈帧的内存分配器,必须在使用完成后弹出对应的栈帧才能释放内存。

正确用法示例

Java版本

利用Java的try-with-resources自动管理MemoryStack的生命周期(MemoryStack实现了AutoCloseable,close时会自动弹出栈帧):

class Piep {
    public FloatBuffer translateNRotate(Matrix4f mat4, float angle) {
        mat4.rotation(angle, new Vector3f(0f, 0f, 1f))
            .translate(new Vector3f(0.5f, -0.5f, 0f));
        
        // 在代码块内创建栈帧,自动释放
        try (MemoryStack stack = MemoryStack.stackPush()) {
            FloatBuffer buffer = stack.mallocFloat(16);
            mat4.get(buffer);
            return buffer; // 注意:buffer仅在栈帧存活期间有效,需在此期间传递给OpenGL使用
        }
    }
}

Clojure版本

使用Clojure的with-open来自动关闭MemoryStack(对应弹出栈帧):

(ns learnopengl.transformations
  (:import [org.joml Vector3f Matrix4f]
           [org.lwjgl.system MemoryStack]))

(defn translate-n-rotate
  [mat4 angle]
  (.rotation mat4 (float angle) (Vector3f. 0.0 0.0 1.0))
  (.translate mat4 (Vector3f. 0.5 -0.5 0.0))
  ;; 局部创建栈帧,with-open自动释放
  (with-open [stack (MemoryStack/stackPush)]
    (let [buffer (.mallocFloat stack 16)]
      (.get mat4 buffer)
      buffer))) ; 同样,buffer需在栈帧关闭前完成OpenGL调用

关键要点

  • 不要全局持有MemoryStack实例:MemoryStack的stackPush()会创建新的栈帧,必须通过pop()或AutoCloseable的close()来释放该帧的所有分配内存。
  • 内存有效期:通过MemoryStack分配的Buffer仅在当前栈帧存活期间有效,栈帧释放后Buffer会失效,所以要确保在try-with-resources/with-open代码块内完成对Buffer的使用(比如传递给OpenGL的uniform变量)。
  • 链式调用优化:JOML的方法支持链式调用,可以简化代码结构。

内容的提问来源于stack exchange,提问作者user1785730

火山引擎 最新活动