Skip to content

Commit 0c24631

Browse files
haileysflavorjones
andcommitted
always call sqlite3_finalize in deallocate func
prevents memory leak when `close` is not called before a ResultSet is garbage collected also add coverage for statement resource cleanup Co-authored-by: Mike Dalessio <mike.dalessio@gmail.com>
1 parent 870eecc commit 0c24631

File tree

3 files changed

+41
-1
lines changed

3 files changed

+41
-1
lines changed

ext/sqlite3/statement.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,18 @@
66

77
VALUE cSqlite3Statement;
88

9+
static void
10+
statement_deallocate(void *data)
11+
{
12+
sqlite3StmtRubyPtr s = (sqlite3StmtRubyPtr)data;
13+
14+
if (s->st) {
15+
sqlite3_finalize(s->st);
16+
}
17+
18+
xfree(data);
19+
}
20+
921
static size_t
1022
statement_memsize(const void *data)
1123
{
@@ -18,7 +30,7 @@ static const rb_data_type_t statement_type = {
1830
"SQLite3::Backup",
1931
{
2032
NULL,
21-
RUBY_TYPED_DEFAULT_FREE,
33+
statement_deallocate,
2234
statement_memsize,
2335
},
2436
0,

sqlite3.gemspec

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ Gem::Specification.new do |s|
8989
"test/test_integration_resultset.rb",
9090
"test/test_integration_statement.rb",
9191
"test/test_pragmas.rb",
92+
"test/test_resource_cleanup.rb",
9293
"test/test_result_set.rb",
9394
"test/test_sqlite3.rb",
9495
"test/test_statement.rb",

test/test_resource_cleanup.rb

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
require "helper"
2+
3+
module SQLite3
4+
# these tests will cause ruby_memcheck to report a leak if we're not cleaning up resources
5+
class TestResourceCleanup < SQLite3::TestCase
6+
def test_cleanup_unclosed_database_object
7+
100.times do
8+
SQLite3::Database.new(':memory:')
9+
end
10+
end
11+
12+
def test_cleanup_unclosed_statement_object
13+
100.times do
14+
db = SQLite3::Database.new(':memory:')
15+
db.execute('create table foo(text BLOB)')
16+
db.prepare('select * from foo')
17+
end
18+
end
19+
20+
# def test_cleanup_unclosed_resultset_object
21+
# db = SQLite3::Database.new(':memory:')
22+
# db.execute('create table foo(text BLOB)')
23+
# stmt = db.prepare('select * from foo')
24+
# stmt.execute
25+
# end
26+
end
27+
end

0 commit comments

Comments
 (0)