tags:

views:

59

answers:

2

A normal routine of sqlite3_prepare_v2() + sqlite3_step() + sqlite3_finalize() could contain leak.

It sound ridiculous. But the test code seems to say it. Or I used the sqlite3_*() wrongly.

Appreciate for any reply.

#include <stdio.h> 
#include <unistd.h>     // for usleep() 
#include <sqlite3.h> 


int multi_write (int j); 

sqlite3 *db = NULL; 

int main (void) 
{ 
    int ret = -1; 

    ret = sqlite3_open("test.db", &db); 
    ret = sqlite3_exec(db,"CREATE TABLE data_his (id INTEGER PRIMARY KEY, d1 CHAR(16))", NULL,NULL,NULL); 
    usleep (100000); 


    int j=0; 
    while (1) 
    { 
        multi_write (j++); 
        usleep (2000000); 
        printf ("   ----------- %d\n", j); 
    } 


    ret = sqlite3_close (db); 
    return 0; 
} 


int multi_write (int j) 
{ 
    int ret = -1; 

    char *sql_f = "INSERT OR REPLACE INTO data_his VALUES (%d, %Q)"; 
    char *sql = NULL; 

    sqlite3_stmt *p_stmt = NULL; 


    ret = sqlite3_prepare_v2 (db, "BEGIN TRANSACTION", -1, &p_stmt, NULL); 
    ret = sqlite3_step ( p_stmt ); 
    ret = sqlite3_finalize ( p_stmt ); 

    int i=0; 
    for (i=0; i<100; i++) 
    { 
        sql = sqlite3_mprintf ( sql_f, j*100000 + i, "00000000000068FD"); 

        ret = sqlite3_prepare_v2 (db, sql, -1, &p_stmt, NULL ); 
        sqlite3_free ( sql ); 
        //printf ("sqlite3_prepare_v2(): %d, %s\n", ret, sqlite3_errmsg (db)); 

        ret = sqlite3_step ( p_stmt ); 
        //printf ("sqlite3_step():       %d, %s\n", ret, sqlite3_errmsg (db)); 

        ret = sqlite3_finalize ( p_stmt ); 
        //printf ("sqlite3_finalize():   %d, %s\n\n", ret, sqlite3_errmsg (db)); 
    } 

    ret = sqlite3_prepare_v2 (db, "COMMIT TRANSACTION", -1, &p_stmt, NULL ); 
    ret = sqlite3_step ( p_stmt ); 
    ret = sqlite3_finalize ( p_stmt ); 


    return 0; 
}

And I watch the the process's run by top.

At first, the memory statistics is:

PID     PPID   USER     STAT   VSZ    %MEM  %CPU  COMMAND 
17731   15488  root     S      1104   5%    7%    ./sqlite3multiwrite 

When the printf() in while(1){} of main() prints the 150, the memory statistics is:

PID     PPID   USER     STAT   VSZ    %MEM  %CPU  COMMAND 
17731   15488  root     S      1552   5%    7%    ./sqlite3multiwrite 

It sounds that after 150 for-cycles, the memory used by sqlite3multiwrite increase from 1104KB to 1552KB.

What does it mean? memory leak or other thing?

+2  A: 

Use Valgrind. Growth from 1.1 MB to 1.5 MB is not that big, especially over 150 iterations. SQLite can, for example, do some caching (it reserves some memory in advance).

Try more itarations - maybe there is a threshold value over which your program cannot grow. But Valgrind is the most accurate tool for finding memory leaks.

el.pescado
Thank you very much!you are my first replyer in stackoveflow.com. :)Because my system just have 32M RAM. While the printf() in while(1){} of main() prints the 161939, the process is killed by system automatically.So it sounds that there are real memory leaks in the code.And when shadowing the sqlite3_step(), the process's memory don't increase.It's a confusing thing.It seems to say there is memory leak in sqlite3_step().
reer
Why could not my comment show as multi rows?Why could not my comment show as multi rows?
reer
+1 , Additionally, I find Valgrind's Massif heap profiler tool extremely helpful in exactly this kind of instance.
Tim Post
+1  A: 

I have get the key answer from http://old.nabble.com/Is-there-any-memory-leak-in-the-normal-routine--td28348648.html#a28354683

The sqlite3's cache is the reason, :)

reer