Can anyone who can be bothered, explain why my Vir...
# kotlin-native
d
Can anyone who can be bothered, explain why my Virtual Table test works on Linux(WSL) but not on Windows? It ends with
Process finished with exit code -1073741819 (0xC0000005)
I think it might be a linking issue but I'm not experienced enough to figure it out. https://github.com/Dominaezzz/kotlin-sqlite
m
Copy code
diff --git a/build.gradle.kts b/build.gradle.kts
index fdfcce9..1a56e66 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -31,7 +31,7 @@ konanArtifacts {
 			linkerOpts("-L$/usr/local/lib")
 		}
 		target("mingw") {
-			linkerOpts("-LC:/msys64/mingw64/lib")
+			linkerOpts("-LC:/msys64/mingw64/lib -Wl,-Bstatic -lstdc++ -static")
 		}
 		libraries {
 			artifact("ksqlite")
o
you problem is essentially incorrect memory management of native pointers. sqlite3_prepare_v3 (https://www.sqlite.org/c3ref/prepare.html) assumes a contract, where value written to the
pzTail
pointer is position inside
zSql
, but what is passed inside
zSql
is temporary C string, which is immediately released. Another problem is that module pointer is freed too early. Following patch fixes both problems:
Copy code
diff --git a/build.gradle.kts b/build.gradle.kts
index fdfcce9..2ccfe78 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -5,7 +5,7 @@ plugins {
 konanArtifacts {
 	interop("sqlite3") {
 		target("linux") {
-			compilerOpts("-I/usr/include")
+			compilerOpts("-I/usr/include -I/usr/include/x86_64-linux-gnu")
 		}
 		target("macos") {
 			compilerOpts("-I/usr/local/include -I/opt/local/include")
diff --git a/gradlew b/gradlew
old mode 100644
new mode 100755
diff --git a/src/main/c_interop/sqlite3.def b/src/main/c_interop/sqlite3.def
index a0b1ef6..8647fc7 100644
--- a/src/main/c_interop/sqlite3.def
+++ b/src/main/c_interop/sqlite3.def
@@ -22,6 +22,7 @@ excludedFunctions = sqlite3_mutex_held \
   sqlite3_enable_load_extension \
   sqlite3_load_extension \
   sqlite3_unlock_notify
+noStringConversion = sqlite3_prepare_v3
 
 ---
 struct ksqlite_vtab {
@@ -32,4 +33,4 @@ struct ksqlite_vtab {
 struct ksqlite_vtab_cursor {
   struct sqlite3_vtab_cursor vtab_cursor;
   void* userObj;
-};
\ No newline at end of file
+};
diff --git a/src/main/kotlin/ksqlite/SQLiteDatabase.kt b/src/main/kotlin/ksqlite/SQLiteDatabase.kt
index 652a4cc..7aeb6d8 100644
--- a/src/main/kotlin/ksqlite/SQLiteDatabase.kt
+++ b/src/main/kotlin/ksqlite/SQLiteDatabase.kt
@@ -36,7 +36,7 @@ class SQLiteDatabase(val ptr: CPointer<sqlite3>) {
 	fun prepare(sql: String) : Pair<SQLiteStatement, String?> = memScoped {
 		val tailPtr = alloc<CPointerVar<ByteVar>>()
 		val stmtPtr = alloc<CPointerVar<sqlite3_stmt>>()
-		val result = sqlite3_prepare_v3(ptr, sql, sql.length, 0, stmtPtr.ptr, tailPtr.ptr)
+		val result = sqlite3_prepare_v3(ptr, sql.cstr.getPointer(this), sql.length, 0, stmtPtr.ptr, tailPtr.ptr)
 		if (result != SQLITE_OK) {
 			throw SQLiteError("Cannot prepare statement: ${sqlite3_errstr(result)?.toKString()}, $errorMessage")
 		}
@@ -93,7 +93,7 @@ class SQLiteDatabase(val ptr: CPointer<sqlite3>) {
 
 	fun createModule(name: String, module: SQLiteModule) {
 		val result = memScoped {
-			val rawModule = alloc<sqlite3_module>()
+			val rawModule = nativeHeap.alloc<sqlite3_module>()
 			if (module is SQLiteModule.Persist) { // If not eponymous.
 				rawModule.xCreate = staticCFunction { dbPtr, pAux, argc, argv, ppVTab, pzErr ->
 					val moduleObj = pAux!!.asStableRef<SQLiteModule.Persist>().get()
To solve that and similar problem one could use a memory debugger, for example I used Valgrind on Linux.
code above leaks bit of memory on
rawModule
, so free it using
nativeHeap.free
when module is no longer needed.
d
Wow, I didn't think it would be a memory issue. I find Linux to be too "tolerant" to my mistakes. Can you recommend a memory debugger for Windows?
Are those arguements @msink added to the linkerOpts required for static linking on Windows?
m
Yes, either link it statically or add
c:\msys64\mingw64\bin
to system PATH