简体   繁体   中英

Jna, random Invalid Memory Access error

I have an openvr binding which has a minor problem since a while

Essentially, from time to time, whenever I free the memory of some geometric 3d model (basestation or controller) I get the Error :

"java.lang.Error: Invalid memory access"

This is the test I'm using so far, it loads and free x times a list of models present in the Steam installation folder:

for (i in 0..99)   models.forEach(::loadRenderModel)

fun loadRenderModel(renderModelName: String) {

    var error: EVRRenderModelError

    val rm = vrRenderModels!!

    val pModel = PointerByReference()
    while (true) {
        error = rm.loadRenderModel_Async(renderModelName, pModel)
        if (error != EVRRenderModelError.Loading) break
        Thread.sleep(1)
    }
    val model = RenderModel.ByReference(pModel.value)

    if (error != EVRRenderModelError.None) {
        System.err.println("Unable to load render model $renderModelName - ${error.getName()}")
        return // move on to the next tracked device
    }

    try {
        rm freeRenderModel model
    } catch (e: Error) {
        System.err.println(e)
    }
    println()
}

RenderModel struct in C++ :

struct RenderModel_t
{
    const RenderModel_Vertex_t *rVertexData;    // Vertex data for the mesh
    uint32_t unVertexCount;                     // Number of vertices in the vertex data
    const uint16_t *rIndexData;                 // Indices into the vertex data for each triangle
    uint32_t unTriangleCount;                   // Number of triangles in the mesh. Index count is 3 * TriangleCount
    TextureID_t diffuseTextureId;               // Session unique texture identifier. Rendermodels which share the same texture will have the same id. <0 == texture not present
};

and in Kotlin :

open class RenderModel : Structure {

    /** Vertex data for the mesh    */
    @JvmField
    var rVertexData: RenderModel_Vertex.ByReference? = null
    /** Number of vertices in the vertex data   */
    @JvmField
    var vertexCount = 0
    /** Indices into the vertex data for each triangle  */
    @JvmField
    var rIndexData: ShortByReference? = null
    /** Number of triangles in the mesh. Index count is 3 * TriangleCount   */
    @JvmField
    var triangleCount = 0
    /** Session unique texture identifier. Rendermodels which share the same texture will have the same id. <0 == texture not present   */
    @JvmField
    var diffuseTextureId = INVALID_TEXTURE_ID

    val vertices
        get() = rVertexData?.pointer?.getByteArray(0, vertexCount * RenderModel_Vertex.SIZE)

    val indices
        get() = rIndexData?.pointer?.getByteArray(0, triangleCount * 3 * Short.BYTES)

    constructor()

    constructor(vertexData: RenderModel_Vertex.ByReference, vertexCount: Int, indexData: ShortByReference, triangleCount: Int,
                diffuseTextureId: Int) {
        this.rVertexData = vertexData
        this.vertexCount = vertexCount
        this.rIndexData = indexData
        this.triangleCount = triangleCount
        this.diffuseTextureId = diffuseTextureId
    }

    override fun getFieldOrder()= listOf("rVertexData", "vertexCount", "rIndexData",
            "triangleCount", "diffuseTextureId")

    constructor(peer: Pointer) : super(peer) {
        read()
    }

    class ByReference : RenderModel, Structure.ByReference {
        constructor() : super()
        constructor(peer: Pointer) : super(peer)
    }

    class ByValue : RenderModel(), Structure.ByValue
}

I tend to believe everything so far (regarding class definition) is correct since I do read valid values.

However I keep getting that error from time to time, I checked some pointer values and I didn't spot any weird value

What can it be?

I found a bug in your code, but I can't confirm it is the reason of your failures. It definitely could produce them.

You say

val error = EVRRenderModelError.None

and then

if (error != EVRRenderModelError.None) {

which is a constantly false condition. Normally there's an IntelliJ inspection that warns you about these errors, but it could be disabled in your config.

You should use a var error instead and reassign it within the busy-wait loop of the async call.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM