Browse Source
- Create MatUtils.kt with safe resource management patterns - Fix major Mat leak in ScreenCaptureService.kt image processing pipeline - Fix Mat leaks in EnhancedOCR.kt enhanceImageForOCR() and upscaleImage() - Add Mat.use() extension for automatic cleanup with try-finally - Add useMats() utility for multi-Mat operations - Add releaseSafely() for batch Mat cleanup with error handling Critical stability fix: prevents native memory leaks that cause app crashes during extended detection use. Mat objects now guaranteed to be released even in exception paths. Related: REFACTORING_TASKS.md CRITICAL-001 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>fix/critical-001-opencv-mat-memory-leaks
3 changed files with 194 additions and 58 deletions
@ -0,0 +1,124 @@ |
|||
package com.quillstudios.pokegoalshelper.utils |
|||
|
|||
import org.opencv.core.Mat |
|||
import android.util.Log |
|||
|
|||
/** |
|||
* OpenCV Mat resource management utilities to prevent native memory leaks. |
|||
* |
|||
* Mat objects hold native memory that must be explicitly released to avoid memory leaks. |
|||
* These utilities provide safe patterns for Mat lifecycle management. |
|||
*/ |
|||
object MatUtils { |
|||
private const val TAG = "MatUtils" |
|||
|
|||
/** |
|||
* Execute a block with a Mat resource, ensuring it's properly released. |
|||
* |
|||
* Usage: |
|||
* ```kotlin |
|||
* val result = Mat().use { mat -> |
|||
* // Use mat safely |
|||
* processImage(mat) |
|||
* return@use someResult |
|||
* } |
|||
* ``` |
|||
*/ |
|||
fun <T> Mat.use(block: (Mat) -> T): T { |
|||
try { |
|||
return block(this) |
|||
} finally { |
|||
try { |
|||
this.release() |
|||
} catch (e: Exception) { |
|||
Log.w(TAG, "Warning: Error releasing Mat", e) |
|||
} |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Execute a block with multiple Mat resources, ensuring all are properly released. |
|||
* |
|||
* Usage: |
|||
* ```kotlin |
|||
* val result = useMats(Mat(), Mat()) { mat1, mat2 -> |
|||
* // Use mats safely |
|||
* processImages(mat1, mat2) |
|||
* return@useMats someResult |
|||
* } |
|||
* ``` |
|||
*/ |
|||
fun <T> useMats(mat1: Mat, mat2: Mat, block: (Mat, Mat) -> T): T { |
|||
try { |
|||
return block(mat1, mat2) |
|||
} finally { |
|||
releaseSafely(mat1, mat2) |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Execute a block with three Mat resources. |
|||
*/ |
|||
fun <T> useMats(mat1: Mat, mat2: Mat, mat3: Mat, block: (Mat, Mat, Mat) -> T): T { |
|||
try { |
|||
return block(mat1, mat2, mat3) |
|||
} finally { |
|||
releaseSafely(mat1, mat2, mat3) |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Safely release multiple Mat objects, logging any errors. |
|||
*/ |
|||
fun releaseSafely(vararg mats: Mat) { |
|||
for (mat in mats) { |
|||
try { |
|||
mat.release() |
|||
} catch (e: Exception) { |
|||
Log.w(TAG, "Warning: Error releasing Mat", e) |
|||
} |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Create a Mat with automatic resource management. |
|||
* |
|||
* Usage: |
|||
* ```kotlin |
|||
* val result = createMat { mat -> |
|||
* // mat is automatically released |
|||
* Utils.bitmapToMat(bitmap, mat) |
|||
* processImage(mat) |
|||
* } |
|||
* ``` |
|||
*/ |
|||
fun <T> createMat(block: (Mat) -> T): T { |
|||
return Mat().use(block) |
|||
} |
|||
|
|||
/** |
|||
* Copy a Mat safely with automatic cleanup. |
|||
*/ |
|||
fun Mat.safeCopy(): Mat { |
|||
val copy = Mat() |
|||
try { |
|||
this.copyTo(copy) |
|||
return copy |
|||
} catch (e: Exception) { |
|||
copy.release() |
|||
throw e |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Debug helper to track Mat memory usage. |
|||
*/ |
|||
fun logMatInfo(mat: Mat, label: String) { |
|||
try { |
|||
val bytes = mat.total() * mat.elemSize() |
|||
Log.d(TAG, "$label: Mat ${mat.cols()}x${mat.rows()}, ${mat.channels()} channels, ${bytes} bytes") |
|||
} catch (e: Exception) { |
|||
Log.d(TAG, "$label: Mat is empty or invalid") |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue