Re: [sqlite] Including sqlite3 in a GNU project
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
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
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; }