【问题标题】:EXCEPTION_ACCESS_VIOLATION Error when using stbi_loadEXCEPTION_ACCESS_VIOLATION 使用 stbi_load 时出错
【发布时间】:2021-12-02 19:17:45
【问题描述】:

我正在尝试使用stbi_load 将图像加载到 ByteBuffer 中。但是,控制台中会抛出以下错误

Java 运行时环境检测到致命错误:EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ffb5bb63b8c, pid=5424, tid=0x0000000000001364 JRE 版本:OpenJDK 运行时环境 (8.0_312-b07) (build 1.8.0_312-b) Java VM:OpenJDK 64 位服务器 VM(25.312-b07 混合模式 windows-amd64 压缩 oops) 有问题的框架:C [lwjgl_stb.dll+0x3b8c] 无法写入核心转储。 Windows 客户端版本默认不启用 Minidump 包含更多信息的错误报告文件保存为:C:\Users\nottn\eclipse-workspace\Bon Sea\hs_err_pid5424.log 如果您想提交错误报告,请访问:https://bugzilla.redhat.com/enter_bug.cgi 崩溃发生在 Java 虚拟机之外的本地代码中。请参阅有问题的框架以了解报告错误的位置。

这是产生此错误的代码(请记住,我使用的是 LWJGL 3)

import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.stb.STBImage.*;

import javax.imageio.ImageIO;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.awt.image.BufferedImage;

public class Texture {
    private int id;
    private IntBuffer width, height, n;
    
    public Texture(String filename) 
    {
        BufferedImage bi;
        
        try 
        {
            bi = ImageIO.read(new File("./sprites/" + filename));
            
            width = IntBuffer.allocate(bi.getWidth());
            width.put(bi.getWidth());
            
            height = IntBuffer.allocate(bi.getHeight());
            height.put(bi.getHeight());
            
            n = IntBuffer.allocate(GL_RGBA);
            n.put(GL_RGBA);
            
            ByteBuffer data = stbi_load("/Users/nottn/eclipse-workspace/Bon Sea/sprites/test.png", width, height, n, STBI_rgb_alpha);
            
            id = glGenTextures();
            glBindTexture(GL_TEXTURE_2D, id);
            
            glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
            glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
            
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width.array()[0], height.array()[0], 0, GL_RGBA, GL_BYTE, data);
        }
        catch (IOException e) 
        {
            e.printStackTrace();
        }
    }
    
    public void Bind() {
        glBindTexture(GL_TEXTURE_2D, id);
    }
}

这是生成的日志文件Pastebin Log Here

非常感谢任何有关此错误发生原因的答案。

【问题讨论】:

  • 您有管理员权限吗?由于您缺乏管理员权限,可能会出现此问题。

标签: java lwjgl stb-image


【解决方案1】:

崩溃的原因是您使用了由 Java 数组支持的非直接 NIO 缓冲区,即IntBuffer.allocate(...) 而不是由堆外(本机)虚拟支持的IntBuffer.allocateDirect(...)记忆。

LWJGL 基本上只是将stbi_load(...) 调用转发/定向到本机库。并且为了使本机库能够将内存放入提供的内存区域,该区域必须是实际的“堆外”(堆外:它位于 Java 垃圾收集堆之外)内存区域进程的虚拟内存。

当您调用任何 LWJGL 提供的采用 NIO 缓冲区(例如 stbi_load(...))的方法时,LWJGL 会读取(隐藏的)Buffer.address 字段的值,该字段仅在所述缓冲区是直接(或“堆外”)缓冲区。

对于由 Java 原始数组支持的非直接或(堆上)缓冲区,该字段为0,因此本机库将访问零地址,最终导致崩溃.

为了解决这个问题,您应该创建直接 NIO 缓冲区

有关非直接与直接 NIO 缓冲区的解释,请参阅the JavaDocs of the ByteBuffer class

我还强烈推荐阅读this LWJGL 3 blog article,它提供了关于 LWJGL 3 中本机内存管理的更多见解和更多策略。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-22
    • 1970-01-01
    • 1970-01-01
    • 2011-12-25
    • 2014-02-01
    相关资源
    最近更新 更多