I believe the following quick start example contains a possible memory 
leak. This is the program found at the following link:

  http://www.sqlite.org/quickstart.html

The error can be reproduced by compiling the example and running it for 
the following SQL statement:

    ./a.out  tmptable  "drop table junk"


Since the table "junk" does not exist, zErrMsg is first allocated 
 memory (legacy.c:129) in the statement below:

/src/legacy.c (line 129)

  if( rc!=SQLITE_OK && rc==sqlite3_errcode(db) && pzErrMsg ){
    *pzErrMsg = malloc(1+strlen(sqlite3_errmsg(db)));
 

However, it appears that this memory is not freed. Not even in 
sqlite3_close(db).  Shown below the valgrind statement and
the report.


 valgrind --logfile=valgrind.output --leak-check=yes  --tool=memcheck ./a.out 
tmptable "drop table junk"



==31665== LEAK SUMMARY:
==31665==    definitely lost: 20 bytes in 1 blocks.
==31665==    possibly lost:   0 bytes in 0 blocks.
==31665==    still reachable: 128 bytes in 2 blocks.
==31665==         suppressed: 0 bytes in 0 blocks.
==31665== Reachable blocks (those to which a pointer was found) are not shown.
==31665== To see them, rerun with: --show-reachable=yes



FIX:

 rc = sqlite3_exec(db, argv[2], callback, 0, &zErrMsg);
  if( rc!=SQLITE_OK ){
    fprintf(stderr, "SQL error: %s\n", zErrMsg);
    /* This will free zErrMsg if assigned */
    if (zErrMsg)
      free(zErrMsg);
  }


After making the following change, valgrind reports no memory leaks.


Why It My Be Relevant:

 Some SQL commands seemed to be ignored by design. For example,
SQLite can indirectly support the "DROP TABLE IF EXIST junk" by
executing the "drop table junk" and ignoring the error. However, when
there are many such statements, with long running programs, the
memory is never freed. At least I believe it is not. 

If the above is correct, changing the example my help users.


Regards,

Mike Chirico




















#include <stdio.h>
#include <sqlite3.h>

static int callback(void *NotUsed, int argc, char **argv, char **azColName){
  int i;
  for(i=0; i<argc; i++){
    printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
  }
  printf("\n");
  return 0;
}

int main(int argc, char **argv){
  sqlite3 *db;
  char *zErrMsg = 0;
  int rc;

  if( argc!=3 ){
    fprintf(stderr, "Usage: %s DATABASE SQL-STATEMENT\n", argv[0]);
    exit(1);
  }
  rc = sqlite3_open(argv[1], &db);
  if( rc ){
    fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
    sqlite3_close(db);
    exit(1);
  }
  rc = sqlite3_exec(db, argv[2], callback, 0, &zErrMsg);
  if( rc!=SQLITE_OK ){
    fprintf(stderr, "SQL error: %s\n", zErrMsg);
/* Problem above zErrMsg is 
 
  }
  sqlite3_close(db);
  return 0;
}


Reply via email to