Hacktoberfest 2026: as issues que os mantenedores marcaram para outubro, abertas e boas para iniciantes. Ver issues do Hacktoberfest

SQLCipherStatement.close() never closes its Cursor, leaking a CursorWindow per Room query

Aberta Para iniciantes
#97 1 comentário 0 reações 0 responsáveis Ver no GitHub

Ninguém assumiu esta issue ainda.

Avaliação

Dificuldade
2/5
Tempo estimado
1-3 horas
Facilidade para iniciantes
72/100
Tipo de issue
Bug
Clareza
Claramente especificada
Status de atividade
Ativa
Stack de tecnologia
android, java, sqlite
Domínio
databases, mobile-dev

Direção de pesquisa

O erro está em SQLCipherStatement, onde close() define closed = true sem fechar o campo cursor que step() cria, enquanto reset() já o fecha e anula o campo. Comece lendo lado a lado os métodos reset() e close() e confirme que o cursor nunca é liberado no caminho de close(). Está pronto quando close() fecha e anula o cursor quando ele está aberto, antes de definir closed, e um teste ou uma verificação do heap mostra que a memória nativa é liberada após muitas leituras pontuais sem GC manual.

Escrita pelo modelo de indexação a partir do texto da issue.

Descrição

SQLCipherStatement.close() sets closed = true and never closes the Cursor that step() created. Only reset() closes it:

public void reset() {
    if (cursor != null) {
        cursor.close();
        cursor = null;
    }
    stepped = false;
}

public void close() {
    closed = true;
}

Room 3 (androidx.room3 3.0.3) prepares, steps and closes a statement per query, and it never calls reset() before close(). So every query leaves a CursorWindow for the finalizer to free.

Versions: sqlcipher-android 4.18.0 through 4.19.1 and the current default branch, with Room 3.0.3 and SQLCipherDriver.

Measured: we ran 20,000 point reads of one 20 KB row through Room with SQLCipherDriver, on Android emulators, with no manual GC.

API 36 API 29
SQLCipherDriver as shipped +72 MB native heap +244 MB native heap
close() calling reset() first under 4 MB (0 KB after GC) under 4 MB

The framework's AndroidSQLiteDriver showed 24 KB over the same reads.

Workaround: we wrap the driver so that each statement's close() calls reset() first:

private class CursorClosingStatement(private val delegate: SQLiteStatement) : SQLiteStatement by delegate {
    override fun close() {
        delegate.reset()
        delegate.close()
    }
}

Suggested fix: in close(), close the cursor if it is open, as reset() does, before setting closed = true.

Linguagem predominante
Java
Estrelas
277
Forks
39
Merge médio
1d 11h
PRs com merge (30d)
1

Preparar o ambiente

Este projeto não oferece contêiner de desenvolvimento, Dockerfile nem guia de contribuição, então a configuração fica por sua conta: comece pelo README e veja nosso guia da primeira contribuição para os passos gerais.

Primeiros passos

  1. Leia a issue inteira e depois o guia de contribuição do projeto.
  2. Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
  3. Faça um fork do repositório e trabalhe em uma branch.
  4. Abra um pull request que referencie o número da issue.

Mais de sqlcipher/sqlcipher-android

Todas as issues de sqlcipher/sqlcipher-android

Issues semelhantes

Mais issues de Java

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.