Re: [sqlite] Including sqlite3 in a GNU project

2005-09-24 Thread Mike Chirico
On Thu, Sep 22, 2005 at 07:23:57AM -0700, Doug Hanks wrote:
> Has anyone went through (what I feel is a painful process) of adding
> sqlite in a GNU project?

The following may help, which is a small package:
   http://ftp1.sourceforge.net/souptonuts/quota_examples.tar.gz
or
   http://ftp1.sourceforge.net/cpearls/simple_but_common_cpp.tar.gz

I put the following in my configure.in or configure.am file which
checks for version 3 of sqlite.

  AC_CHECK_LIB(sqlite3,sqlite3_open,[],found=no)

This is the full configure.in file


AC_INIT(getquota.c)
AC_PROG_CXX

if test -f VERSION; then
  VERSION=`cat VERSION`
  echo "Version set to $VERSION"
else
  VERSION='0.0.0'
fi
AM_INIT_AUTOMAKE(quota_examples, $VERSION )
AC_PROG_CXX
CXXFLAGS='-Wall -W -O2 -s -pipe'
CFLAGS='-Wall -W -O2 -s -pipe'  


AM_CONDITIONAL(HAVE_SQLITE, true)
AC_CHECK_LIB(sqlite3,sqlite3_open,[],found=no)
 if test "$found" = "no"; then
   AC_CHECK_FILE(/usr/local/lib/libsqlite3.a, found=yes)
   if test "$found" = "yes"; then
 SQLLIBS="-lsqlite3 "
 INCLUDES="$INCLUDES -I/usr/local/include"
 EXTRALIB='-L/usr/local/lib'
else
 AM_CONDITIONAL(HAVE_SQLITE, false)
 echo ""
 echo " 
---"
 echo "| Are you SURE sqlite3 is installed? 
   |"
 echo "|  You need to try this: 
   |"
 echo "|export LDFLAGS='-L/usr/'   |"
 echo "| ./configure
   |"
 echo " 
---" 
 echo "|  Will not compile the sqlite programs. But, why not install 
SQLite?   |"
 echo "|   $ wget http://www.sqlite.org/sqlite-3.2.2.tar.gz 
   |"
 echo " 
---" 
 echo ""
   fi
 else
   SQLLIBS="$LIBS"
   LIBS=""
 fi
SQLIBOBJS='-Wl,-R/usr/local/lib'
AC_SUBST(SQLIBOBJS)
AC_SUBST(SQLLIBS)
AC_SUBST(INCLUDES)
AC_SUBST(EXTRALIB)
AC_OUTPUT(Makefile)


Below is an example of the Makefile.am that goes with the 
configure.in above.

if HAVE_SQLITE
bin_PROGRAMS = getquota setquotas quotadb
else
bin_PROGRAMS = getquota setquotas 
endif

getquota_SOURCES = getquota.c quota.h


setquotas_SOURCES = setquotas.c quota.h


quotadb_SOURCES = quotadb.c quota.h
quotadb_LDADD =  @INCLUDES@ @SQLIBOBJS@ @EXTRALIB@ @SQLLIBS@


Hope with helps. 

Regards,

Mike Chirico


[sqlite] Quick Start Example Potential Memory Leak: zErrMsg

2005-09-11 Thread Mike Chirico
I believe the following quick start example leaves
the program open to a potential memory leak when
the call to sqlite3_exec is not equal to SQLITE_OK 
because zErrMsg is not explicitly freed.

Reference the example:

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

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

  $ gcc quickstart.c  -Wall -W -O2 -Wl,-R/usr/local/lib \
-lsqlite3


Now execute the following statement.

  $ ./a.out tmptable "drop table junk"

Since the table "junk" does not exist, zErrMsg gets memory allocated
to it (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)));
  
That's fine. But it's up to the user to free this memory. It
is not freed in sqlite3_close(db). To demonstrate this finding,
examine the report from valgrind.

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


==24040== LEAK SUMMARY:
==24040==definitely lost: 20 bytes in 1 blocks.
==24040==  possibly lost: 0 bytes in 0 blocks.
==24040==still reachable: 128 bytes in 2 blocks.
==24040== suppressed: 0 bytes in 0 blocks.


FIX

To fix the problem, add the following 3 lines to the example after
the fprintf statement.

 /* This will free zErrMsg if assigned */
if (zErrMsg)
  free(zErrMsg);


Below is the complete example as I believe it should be


#include 
#include 

static int callback(void *NotUsed, int argc, char **argv, char **azColName){

  NotUsed=0;
  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], );
  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, );
  if( rc!=SQLITE_OK ){
fprintf(stderr, "SQL error: %s\n", zErrMsg);
/* This will free zErrMsg if assigned */
if (zErrMsg)
  free(zErrMsg);

  }
  sqlite3_close(db);
  return 0;
}

Now if this program is compiled and run with valgrind, you'll get the 
following output.

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



==6510== LEAK SUMMARY:
==6510==definitely lost: 0 bytes in 0 blocks.
==6510==  possibly lost: 0 bytes in 0 blocks.
==6510==still reachable: 128 bytes in 2 blocks.
==6510== suppressed: 0 bytes in 0 blocks.


Note the difference above.


Why This is Relevant:

Long running SQLite programs could cause potential memory leaks
with multiple failed calls, if the zErrMsg is not freed. It would 
be helpful to inform the user, with the first example, that it is
the programmers responsibility to free this variable.


Another example can be seen in the "SQLite Tutorial" in the
section C and C++ API. Reference the following link:

 http://souptonuts.sourceforge.net/readme_sqlite_tutorial.html


Regards,

Mike Chirico


[sqlite] Quick start example contains possible memory leak: zErrMsg

2005-07-28 Thread mike . chirico
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, );
  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 
#include 

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], );
  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, );
  if( rc!=SQLITE_OK ){
fprintf(stderr, "SQL error: %s\n", zErrMsg);
/* Problem above zErrMsg is 
 
  }
  sqlite3_close(db);
  return 0;
}