issue #26: the reason was the dangling pointer?

This commit is contained in:
minjaesong
2019-06-23 02:20:01 +09:00
parent 601afc2636
commit 4e89a32e4e
4 changed files with 41 additions and 41 deletions

View File

@@ -37,10 +37,10 @@ class UnsafePtr(val ptr: Long, val allocSize: Long) {
} }
private inline fun checkNullPtr(index: Long) { private inline fun checkNullPtr(index: Long) {
if (destroyed) throw NullPointerException() if (destroyed) throw NullPointerException("The pointer is already destroyed (0x${ptr.toString(16)})")
// OOB Check: debugging purposes only -- comment out for the production // OOB Check: debugging purposes only -- comment out for the production
//if (index !in 0 until allocSize) throw NullPointerException("Out of bounds: $index; alloc size: $allocSize") //if (index !in 0 until allocSize) throw IndexOutOfBoundsException("Index: $index; alloc size: $allocSize")
} }
operator fun get(index: Long): Byte { operator fun get(index: Long): Byte {
@@ -63,4 +63,8 @@ class UnsafePtr(val ptr: Long, val allocSize: Long) {
UnsafeHelper.unsafe.putFloat(ptr + index, value) UnsafeHelper.unsafe.putFloat(ptr + index, value)
} }
fun fillWith(byte: Byte) {
UnsafeHelper.unsafe.setMemory(ptr, allocSize, byte)
}
} }

View File

@@ -13,7 +13,7 @@ internal class UnsafeCvecArray(val width: Int, val height: Int) {
private inline fun toAddr(x: Int, y: Int) = 16L * (y * width + x) private inline fun toAddr(x: Int, y: Int) = 16L * (y * width + x)
fun zerofill() = UnsafeHelper.unsafe.setMemory(this.array.ptr, TOTAL_SIZE_IN_BYTES, 0) fun zerofill() = array.fillWith(0)
init { init {
zerofill() zerofill()

View File

@@ -1,8 +1,8 @@
package net.torvald.terrarum.gameworld package net.torvald.terrarum.gameworld
import com.badlogic.gdx.utils.Disposable import com.badlogic.gdx.utils.Disposable
import net.torvald.UnsafeHelper
import net.torvald.terrarum.AppLoader.printdbg import net.torvald.terrarum.AppLoader.printdbg
import java.nio.ByteBuffer
/** /**
* Original version Created by minjaesong on 2016-01-17. * Original version Created by minjaesong on 2016-01-17.
@@ -12,23 +12,14 @@ import java.nio.ByteBuffer
*/ */
open class BlockLayer(val width: Int, val height: Int) : Disposable { open class BlockLayer(val width: Int, val height: Int) : Disposable {
private var unsafeArrayDestroyed = false private val ptr = UnsafeHelper.allocate(width * height * BYTES_PER_BLOCK)
/*private val unsafe: Unsafe //private val directByteBuffer: ByteBuffer
init {
val unsafeConstructor = Unsafe::class.java.getDeclaredConstructor()
unsafeConstructor.isAccessible = true
unsafe = unsafeConstructor.newInstance()
}
private val layerPtr = unsafe.allocateMemory(width * height * BYTES_PER_BLOCK.toLong())*/
private val directByteBuffer: ByteBuffer
init { init {
//unsafe.setMemory(layerPtr, width * height * BYTES_PER_BLOCK.toLong(), 0) // does reliably fill the memory with zeroes ptr.fillWith(0)
directByteBuffer = ByteBuffer.allocateDirect(width * height * BYTES_PER_BLOCK) //directByteBuffer = ByteBuffer.allocateDirect(width * height * BYTES_PER_BLOCK)
} }
/** /**
@@ -71,13 +62,13 @@ open class BlockLayer(val width: Int, val height: Int) : Disposable {
// advance counter // advance counter
iteratorCount += 2 iteratorCount += 2
val offset = 2 * (y * width + x) val offset = 2L * (y * width + x)
//val lsb = unsafe.getByte(layerPtr + offset) val lsb = ptr[offset]
val lsb = directByteBuffer[offset] //val lsb = directByteBuffer[offset]
//val msb = unsafe.getByte(layerPtr + offset + 1) val msb = ptr[offset + 1]
val msb = directByteBuffer[offset + 1] //val msb = directByteBuffer[offset + 1]
//return data[y * width + x]
return lsb.toUint() + msb.toUint().shl(8) return lsb.toUint() + msb.toUint().shl(8)
} }
} }
@@ -91,7 +82,7 @@ open class BlockLayer(val width: Int, val height: Int) : Disposable {
fun bytesIterator(): Iterator<Byte> { fun bytesIterator(): Iterator<Byte> {
return object : Iterator<Byte> { return object : Iterator<Byte> {
private var iteratorCount = 0 private var iteratorCount = 0L
override fun hasNext(): Boolean { override fun hasNext(): Boolean {
return iteratorCount < width * height return iteratorCount < width * height
@@ -100,18 +91,18 @@ open class BlockLayer(val width: Int, val height: Int) : Disposable {
override fun next(): Byte { override fun next(): Byte {
iteratorCount += 1 iteratorCount += 1
//return unsafe.getByte(layerPtr + iteratorCount) return ptr[iteratorCount]
return directByteBuffer[iteratorCount] //return directByteBuffer[iteratorCount]
} }
} }
} }
internal fun unsafeGetTile(x: Int, y: Int): Int { internal fun unsafeGetTile(x: Int, y: Int): Int {
val offset = BYTES_PER_BLOCK * (y * width + x) val offset = BYTES_PER_BLOCK * (y * width + x)
//val lsb = unsafe.getByte(layerPtr + offset) val lsb = ptr[offset]
//val msb = unsafe.getByte(layerPtr + offset + 1) val msb = ptr[offset + 1]
val lsb = directByteBuffer[offset] //val lsb = directByteBuffer[offset]
val msb = directByteBuffer[offset + 1] //val msb = directByteBuffer[offset + 1]
return lsb.toUint() + msb.toUint().shl(8) return lsb.toUint() + msb.toUint().shl(8)
} }
@@ -123,10 +114,10 @@ open class BlockLayer(val width: Int, val height: Int) : Disposable {
val msb = tile.ushr(8).and(0xff).toByte() val msb = tile.ushr(8).and(0xff).toByte()
directByteBuffer.put(offset, lsb) ptr[offset] = lsb
directByteBuffer.put(offset + 1, msb) ptr[offset + 1] = msb
//unsafe.putByte(layerPtr + offset, lsb) //directByteBuffer.put(offset, lsb)
//unsafe.putByte(layerPtr + offset + 1, msb) //directByteBuffer.put(offset + 1, msb)
} }
/** /**
@@ -145,16 +136,15 @@ open class BlockLayer(val width: Int, val height: Int) : Disposable {
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height) fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
override fun dispose() { override fun dispose() {
if (!unsafeArrayDestroyed) { ptr.destroy()
//unsafe.freeMemory(layerPtr) //directByteBuffer.clear()
directByteBuffer.clear() printdbg(this, "BlockLayer successfully freed")
unsafeArrayDestroyed = true
printdbg(this, "BlockLayer successfully freed")
}
} }
internal fun getPtr() = ptr.ptr
companion object { companion object {
@Transient val BYTES_PER_BLOCK = 2 @Transient val BYTES_PER_BLOCK = 2L
} }
} }

View File

@@ -211,6 +211,12 @@ object LightmapRenderer {
catch (e: UninitializedPropertyAccessException) { catch (e: UninitializedPropertyAccessException) {
return // quit prematurely return // quit prematurely
} }
catch (e: NullPointerException) {
System.err.println("[LightmapRendererNew.fireRecalculateEvent] Attempted to refer destroyed unsafe array " +
"(world size: ${world.layerTerrain.width} x ${world.layerTerrain.height}; " +
"ptr: 0x${world.layerTerrain.getPtr().toString(16)})")
return
}
if (world.worldIndex == -1) return if (world.worldIndex == -1) return