diff --git a/ext/sqlite3/statement.c b/ext/sqlite3/statement.c index 99607c17..62fea2a3 100644 --- a/ext/sqlite3/statement.c +++ b/ext/sqlite3/statement.c @@ -6,6 +6,18 @@ VALUE cSqlite3Statement; +static void +statement_deallocate(void *data) +{ + sqlite3StmtRubyPtr s = (sqlite3StmtRubyPtr)data; + + if (s->st) { + sqlite3_finalize(s->st); + } + + xfree(data); +} + static size_t statement_memsize(const void *data) { @@ -18,7 +30,7 @@ static const rb_data_type_t statement_type = { "SQLite3::Backup", { NULL, - RUBY_TYPED_DEFAULT_FREE, + statement_deallocate, statement_memsize, }, 0, diff --git a/sqlite3.gemspec b/sqlite3.gemspec index b44d42e8..9fe6c590 100644 --- a/sqlite3.gemspec +++ b/sqlite3.gemspec @@ -89,6 +89,7 @@ Gem::Specification.new do |s| "test/test_integration_resultset.rb", "test/test_integration_statement.rb", "test/test_pragmas.rb", + "test/test_resource_cleanup.rb", "test/test_result_set.rb", "test/test_sqlite3.rb", "test/test_statement.rb", diff --git a/test/test_resource_cleanup.rb b/test/test_resource_cleanup.rb new file mode 100644 index 00000000..ec32c929 --- /dev/null +++ b/test/test_resource_cleanup.rb @@ -0,0 +1,27 @@ +require "helper" + +module SQLite3 + # these tests will cause ruby_memcheck to report a leak if we're not cleaning up resources + class TestResourceCleanup < SQLite3::TestCase + def test_cleanup_unclosed_database_object + 100.times do + SQLite3::Database.new(':memory:') + end + end + + def test_cleanup_unclosed_statement_object + 100.times do + db = SQLite3::Database.new(':memory:') + db.execute('create table foo(text BLOB)') + db.prepare('select * from foo') + end + end + + # def test_cleanup_unclosed_resultset_object + # db = SQLite3::Database.new(':memory:') + # db.execute('create table foo(text BLOB)') + # stmt = db.prepare('select * from foo') + # stmt.execute + # end + end +end