vrischmann / zig-sqlite

zig-sqlite is a small wrapper around sqlite's C API, making it easier to use with Zig.
MIT License
367 stars 49 forks source link

Illegal instruction at zig-sqlite/c/sqlite3.c:35765:20 #138

Closed margual56 closed 1 year ago

margual56 commented 1 year ago

zig-sqlite commit

19535aab5760eeaf2979a9dadfca3bb21d1594b9

Zig version

0.11.0

Steps to reproduce

Context: I am using the built-in version of sqlite, the one included with this library.

  1. Have a struct that holds a pointer to a database:

        // Create database object
        var db = try sqlite.Db.init(.{
            .mode = sqlite.Db.Mode{ .File = db_path },
            .open_flags = .{
                .write = true,
                .create = true,
            },
            .threading_mode = .MultiThread,
        });
    
        return .{ .db = &db, .files = &files, .next_id = next_id };
  2. Try to prepare a statement inside a function

        var stmt = try self.db.prepare(query);
        defer stmt.deinit();
    
        try stmt.exec(.{}, .{
            self.next_id,
            new_file.timestamp,
            fmt_path,
            new_file.hash,
        });
  3. Observe an error when preparing the statement:

    
    steps [2/6] zig build-exe syntholink Debug native-native-gnu.2.28... LLVM Emit Object...

Illegal instruction at address 0x34c593 libs/zig-sqlite/c/sqlite3.c:35765:20: 0x34c593 in sqlite3SafetyCheckOk eOpenState = db->eOpenState; ^ libs/zig-sqlite/c/sqlite3.c:140165:8: 0x34e5b8 in sqlite3LockAndPrepare if( !sqlite3SafetyCheckOk(db)||zSql==0 ){ ^ libs/zig-sqlite/c/sqlite3.c:140281:8: 0x34e938 in sqlite3_prepare_v3 rc = sqlite3LockAndPrepare(db,zSql,nBytes, ^ zig-sqlite/sqlite.zig:1521:48: 0x2abf85 in prepare const result = c.sqlite3_prepare_v3( ^ zig-sqlite/sqlite.zig:1981:61: 0x277d76 in prepare .dynamic_stmt = try DynamicStatement.prepare(db, query.getQuery(), options, flags), ^ zig-sqlite/sqlite.zig:516:49: 0x26db07 in prepare__anon_8127 return StatementType(.{}, query).prepare(self, .{}, 0); ^

    var stmt = try self.db.prepare(query);


Note that I have checked that the database exists, I have permission to open and write to it and that the query is correct (I can run it manually).

### Expected behaviour

The database opens correctly when preparing a statement.
margual56 commented 1 year ago

Forgot to mention that the program already runs a query before that to create the table, and that query runs just fine. The issue seems to be with the insert...

margual56 commented 1 year ago

The issue seems to be with passing around a reference to the database... Why would this be an issue? Isn't there a better way to do this than to initialize the database every time the function is called?

vrischmann commented 1 year ago

This is wrong:

  // Create database object
        var db = try sqlite.Db.init(.{
            .mode = sqlite.Db.Mode{ .File = db_path },
            .open_flags = .{
                .write = true,
                .create = true,
            },
            .threading_mode = .MultiThread,
        });

        return .{ .db = &db, .files = &files, .next_id = next_id };

db is stack allocated and invalid after you return. You can either pass the db object around (the value, not a pointer) or you need to restructure your code to make sure the db object outlives anything that keeps a pointer to it.

margual56 commented 1 year ago

That makes sense, thank you! Should I close the issue?

vrischmann commented 1 year ago

No worries ! I'll close the issue.