java - 尝试释放内存时出现 EXCEPTION_ACCESS_VIOLATION (0xc0000005)

标签 java opencl lwjgl

通过 LWJGL 使用 opencl 时,我收到以下错误消息:

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x0000000002201971, pid=8476, tid=8920
#
# JRE version: 7.0_03-b05
# Java VM: Java HotSpot(TM) 64-Bit Server VM (22.1-b02 mixed mode windows-amd64     compressed oops)
# Problematic frame:
# C  [OpenCL.dll+0x1971]
#
# Failed to write core dump. Minidumps are not enabled by default on client versions of    Windows
#
# An error report file with more information is saved as:
# V:\Documents\NetBeansProjects\LWJGL\hs_err_pid8476.log
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.sun.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#

我正在使用的源代码:

import java.awt.*;
import java.awt.image.*;
import java.io.*;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.*;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.vecmath.Point3f;
import org.lwjgl.*;
import static org.lwjgl.opencl.CL10.*;
import org.lwjgl.opencl.*;

public class RayTracer {
    public static void main(String[] args) throws Exception {
        LoadSource();
        RayTracer rayTracer = new RayTracer();
        rayTracer.CLRender();
    }
    JFrame frame;
    BufferedImage scene;
    Sphere sphere;
    static final float SAMPLES = 4f;
    Graphics graphics;
    BufferStrategy bufferSrategy;
    final AtomicBoolean redraw = new AtomicBoolean();
    IntBuffer temp;
    static String source = "";

RayTracer() throws LWJGLException {
    frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
    frame.setVisible(true);

    frame.createBufferStrategy(2);
    bufferSrategy = frame.getBufferStrategy();

    GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
    GraphicsDevice gd = ge.getDefaultScreenDevice();
    GraphicsConfiguration gc = gd.getDefaultConfiguration();

    scene = gc.createCompatibleImage((int) (frame.getWidth()), (int) (frame.getHeight()));
    sphere = new Sphere();
    sphere.location = new Point3f(0, 0, -5);
    startDrawThread();

}

void CLRender() throws LWJGLException {


        // initialization
        CL.create();
        CLPlatform platform = CLPlatform.getPlatforms().get(0);
        List<CLDevice> devices = platform.getDevices(CL_DEVICE_TYPE_GPU);
        CLContext context = CLContext.create(platform, devices, null, null, null);
        CLCommandQueue queue = clCreateCommandQueue(context, devices.get(0), CL_QUEUE_PROFILING_ENABLE, null);



        // program/kernel creation

        CLProgram program = clCreateProgramWithSource(context, source, null);
        try {
            Util.checkCLError(clBuildProgram(program, devices.get(0), "", null));
            //check for problem
        } catch (OpenCLException e) {
            ByteBuffer buffer = BufferUtils.createByteBuffer(1024 * 40);
            buffer.rewind();
            PointerBuffer pb = PointerBuffer.allocateDirect(1);
            Util.checkCLError(clGetProgramBuildInfo(program, devices.get(0), CL_PROGRAM_BUILD_STATUS, buffer, null));
            switch (buffer.get(0)) {
                case CL_BUILD_NONE:
                    System.out.println("build none");
                    break;
                case CL_BUILD_ERROR:
                    System.out.println("build error");
                    break;
                case CL_BUILD_IN_PROGRESS:
                    System.out.println("build in progress");
                    break;
                case CL_BUILD_SUCCESS:
                    System.out.println("build successful");
                    break;
            }
            buffer.rewind();
            Util.checkCLError(clGetProgramBuildInfo(program, devices.get(0), CL_PROGRAM_BUILD_LOG, buffer, pb));
            print(buffer, pb.get());
            System.exit(1);
        }
        // set kernel
        CLKernel kernel = clCreateKernel(program, "trace", null);
        final int width = scene.getWidth();
        final int height = scene.getHeight();
        FloatBuffer sphereRadius, sphereLocation, light, imageDim, samples;
        IntBuffer color;
        Light movingLight = new Light(new Point3f(), Color.ORANGE);
        movingLight.activate();
        try {
            for (float z = 0;; z += .01f) {
                //set Ligh Poition
                movingLight.position = new Point3f(-.5f, (float) (10 * Math.cos(z)), (float) (10 * Math.sin(z)));

                //Put data in Buffers
                float[] lights = Light.getLights();
                sphereRadius = toFloatBuffer(new float[]{sphere.radius.x, sphere.radius.y, sphere.radius.z});
                sphereLocation = toFloatBuffer(new float[]{sphere.location.x, sphere.location.y, sphere.location.z});
                light = toFloatBuffer(lights);
                imageDim = toFloatBuffer(new float[]{width, height, -1f});
                samples = toFloatBuffer(new float[]{SAMPLES});
                color = toIntBuffer(new int[width * height]);


                // send to open CL
                CLMem sphereRadiusMem = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sphereRadius, null);
                clEnqueueWriteBuffer(queue, sphereRadiusMem, 1, 0, sphereRadius, null, null);
                CLMem lightMem = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, light, null);
                clEnqueueWriteBuffer(queue, lightMem, 1, 0, light, null, null);
                CLMem imageDimMem = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, imageDim, null);
                clEnqueueWriteBuffer(queue, imageDimMem, 1, 0, imageDim, null, null);
                CLMem samplesMem = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, samples, null);
                clEnqueueWriteBuffer(queue, samplesMem, 1, 0, samples, null, null);
                CLMem sphereLocationMem = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sphereLocation, null);
                clEnqueueWriteBuffer(queue, sphereLocationMem, 1, 0, sphereLocation, null, null);
                CLMem colorMem = clCreateBuffer(context, CL_MEM_WRITE_ONLY | CL_MEM_COPY_HOST_PTR, color, null);

                // execution
                PointerBuffer kernel1DGlobalWorkSize = BufferUtils.createPointerBuffer(2);
                kernel1DGlobalWorkSize.put(0, width);
                kernel1DGlobalWorkSize.put(1, height);
                kernel.setArg(0, sphereRadiusMem);
                kernel.setArg(1, sphereLocationMem);
                kernel.setArg(2, lightMem);
                kernel.setArg(3, imageDimMem);
                kernel.setArg(4, samplesMem);
                kernel.setArg(5, colorMem);
                clEnqueueNDRangeKernel(queue, kernel, 2, null, kernel1DGlobalWorkSize, null, null, null);

                // read the results back
                clEnqueueReadBuffer(queue, colorMem, 1, 0, color, null, null);

                //transfer to Image
                setScene(color);

                //clean up memory
                clReleaseMemObject(colorMem);
                clReleaseMemObject(imageDimMem);
                clReleaseMemObject(lightMem);
                clReleaseMemObject(samplesMem);
                //clReleaseMemObject(sphereLocationMem);    //uncomenting results in nasty error
                clReleaseMemObject(sphereLocationMem);
                clReleaseMemObject(sphereRadiusMem);

            }
        } finally {
            // teardown
            clFinish(queue);
            clReleaseKernel(kernel);
            clReleaseProgram(program);
            clReleaseCommandQueue(queue);
            CL.destroy();
        }
    }
}

在底部附近,您将看到一个带注释的 clReleaseMemObject(sphereLocationMem); 当取消注释时,我会收到错误消息。如果我留下评论,它就可以正常工作。所有其他对 clReleaseMemory() 的调用都工作正常,为什么这个会抛出错误?

最佳答案

当指定行取消注释时,

SphereLocationMem 被释放两次,位于:

//clReleaseMemObject(sphereLocationMem);    //uncomenting results in nasty error
clReleaseMemObject(sphereLocationMem);

导致指示的访问冲突。对该行进行注释后,它很可能工作正常。

关于java - 尝试释放内存时出现 EXCEPTION_ACCESS_VIOLATION (0xc0000005),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14147639/

相关文章:

java - 将对象转换为日期

java - 您建议新手学习 Web 服务的计划是什么?

c# - 有没有办法在没有第 3 方插件的情况下对 OpenCL 进行编程? C#

java - 在(使用 LWJGL 和 slick2D 的 java 游戏)中绘制字符串无法正常工作

java - 有没有办法让 Netbeans 中的代码自动完成

java - 使用首选项 MenuItem SWT

c - 如果没有 ICD 加载程序扩展,OpenCL 如何工作?

c++ - 我应该用什么代替 cl::KernelFunctor?

java - LWJGL:无法在 opengl 中渲染多个形状

java - LWJGL Vector2f慢慢变成另一个 vector