sqlite3_close不会关闭db并且不会在C中返回任何错误

时间:2013-10-15 10:58:30

标签: c sqlite

我写了一个sqlite C程序的例子,它尝试创建一个DB及其表并连续插入其表。但我的程序没有关闭它打开的数据库,它也有内存泄漏。 我找不到自己的错误。 这是我的C代码:

 #include <stdio.h>
 #include <stdlib.h>
 #include <sqlite3.h>
 #include <string.h>
 #include <time.h>
 #define SQLITE_MAIN_BASE "/var/"
 #define SQLITE_DEVLOG_BASE  "./"
 #define Create_All_Database_Error 1
 void addlog(const char * logtext,const char *logpath)
 {
      struct tm *timeinfo;
      time_t rawtime;
      if (logpath != NULL )
      {
          if (strlen(logpath) > 4)
          {
              FILE *Lfile;
              Lfile = fopen(logpath,"a");
              if (Lfile)
              {
                  char cur_dtime[50];
                  time ( &rawtime );
                  timeinfo = localtime (&rawtime);
                  strcpy(cur_dtime,asctime(timeinfo));
                  cur_dtime[strlen(cur_dtime)-1] = '\0';
                  fputs(cur_dtime,Lfile);
                  fputs(" :: ",Lfile);
                  fputs(logtext,Lfile);
                  fputs("\n",Lfile);
                  fclose(Lfile);
              }
              else
              {
                  fprintf(stderr,"can not open log file %s\n",logpath);
              }
          }
      }
 }
 MySqlite_close(sqlite3 *db)
 {
     int i=0,
         rc=0;
     rc=sqlite3_close(db);
     while(rc != SQLITE_OK)
     {
         printf("yet closing\n");
         if (rc == SQLITE_BUSY)
         {
             printf("it is busy\n");
             i++;
             if ( i > 10 )
             {
                 return rc;
             }
         }
         sleep(1);
         rc=sqlite3_close(db);
     }
     printf("2closeeeeeee\n\n");
     return 0;

 }
 int MySqlite_Exec(const char *dbname,const char *query,sqlite3_stmt **retStmt,const char *queryTail2,const char *logpath,int logfd,int mode)
 {
     sqlite3 *db;
     char logmessage[1500];
     char dbfilepath[150];
     int rc=0;
     retStmt=NULL;
     sprintf(dbfilepath,"%s%s",SQLITE_DEVLOG_BASE,dbname);
     fprintf(stdout,"%s\n",query);
 //    fprintf(stdout,"%s\n",dbfilepath);
     rc = sqlite3_open(dbfilepath, &db);
 //    if( rc )
     while(sqlite3_open(dbfilepath, &db))
     {
         sprintf(logmessage,"1Error on \"%s\" : %u  %s ",query,sqlite3_errcode(db), sqlite3_errmsg(db));
         printf("%s\n",logmessage);
 //        addlog(logmessage,logpath);
 //        printf("1\n");
         sleep(10);

         MySqlite_close(db);
 //        return sqlite3_errcode(db);
         return 0;
     }
     printf("10\n");
     if( sqlite3_prepare_v2(db, query, strlen(query)+1, retStmt,NULL) != SQLITE_OK )
     {
         sprintf(logmessage,"2Error on \"%s\" : %u  %s ",query,sqlite3_errcode(db), sqlite3_errmsg(db));
         printf("%s\n",logmessage);
 //        addlog(logmessage,logpath);
         while(sqlite3_prepare_v2(db, query, strlen(query)+1, retStmt,NULL) == SQLITE_BUSY)
         {
             sprintf(logmessage,"2Error on \"%s\" : %u  %s ",query,sqlite3_errcode(db), sqlite3_errmsg(db));
             printf("%s\n",logmessage);
 //            addlog(logmessage,logpath);
             sleep(1);
         }
     }
     printf("12\n");
     if (mode==0)
     {
         printf("222\n");
         if (sqlite3_step(*retStmt) != SQLITE_DONE)
         {
              sprintf(logmessage,"3Error on \"%s\" : %u  %s ",query,sqlite3_errcode(db), sqlite3_errmsg(db));
              printf("%s\n",logmessage);
         }
         if ( *retStmt != NULL )
         {
             printf("retStmt is not NULL\n");
             sqlite3_step(*retStmt);
             while(sqlite3_finalize(*retStmt)!=SQLITE_OK)
             {
                 sprintf(logmessage,"20Error on  : %u  %s ",sqlite3_errcode(db), sqlite3_errmsg(db));
                 printf("%s\n",logmessage);
                 printf("finilized NOT ok\n");
                 sleep(1);
             }
             printf("finilized ok\n");

 //            sqlite3_exec(db, "COMMIT", NULL, NULL, NULL);
         }
         else
         {
             printf("retStmt is NULL\n");
         }
         MySqlite_close(db);
     }
    return 0;
 }

 int Create_SqltDB(void)
 {
     char hostip[20],
          LOG_FILE[100],
          query[1000],
          dbfilepath[100],
          logmessage[1500];
     int result=0;
     const char *queryTail;

     sqlite3_stmt *retStmt;
     sprintf(LOG_FILE,"/var/log/Emain.log");
     sprintf(query,"create table if not exists lastuptime(row integer primary key not NULL,microupdatetime double default 0 not NULL,time double default 0 not NULL);");
     if (MySqlite_Exec("lastuptime",query,&retStmt,queryTail,LOG_FILE,2,0))
     {
         return Create_All_Database_Error;
     }
     int i=0;
     for (i=0; i<1000000;i++)
     {
         sprintf(query,"insert into lastuptime(microupdatetime,time) values (%i,%i);",i,i);
         if (MySqlite_Exec("lastuptime",query,&retStmt,queryTail,LOG_FILE,2,0))
         {
             return Create_All_Database_Error;
         }
     }

     sprintf(query,"select * from lastuptime;");
     if (MySqlite_Exec("lastuptime",query,&retStmt,queryTail,LOG_FILE,2,1))
     {
         return Create_All_Database_Error;
     }

     do
     {
         result = sqlite3_step (retStmt) ;
         if (result == SQLITE_ROW) /* can read data */
         {
             printf(" %d \t|\t %f \t|\t '%f' \n",\
                     sqlite3_column_int(retStmt,0),\
                     sqlite3_column_double(retStmt,1),\
                     sqlite3_column_double(retStmt,2)) ;
         }
         else
         {
             printf("no data\n");
         }
     } while (result == SQLITE_ROW) ;

 }
 int main()
 {
     Create_SqltDB();
     return 0;
 }

这是我的日志:

create table if not exists lastuptime(row integer primary key not NULL,microupdatetime double default 0 not NULL,time double default 0 not NULL);
10
12
222
retStmt is not NULL
finilized ok
2closeeeeeee

insert into lastuptime(microupdatetime,time) values (0,0);
10
12
222
retStmt is not NULL
finilized ok
2closeeeeeee

insert into lastuptime(microupdatetime,time) values (1,1);
10
12
222
retStmt is not NULL
finilized ok
2closeeeeeee
..
..
..
..
.
insert into lastuptime(microupdatetime,time) values (1017,1017);
10
12
222
retStmt is not NULL
finilized ok
2closeeeeeee

insert into lastuptime(microupdatetime,time) values (1018,1018);
10
12
222
3Error on "insert into lastuptime(microupdatetime,time) values (1018,1018);" : 14 unable to open database file
retStmt is not NULL
20Error on : 14 unable to open database file
finilized NOT ok
20Error on : 14 unable to open database file
finilized NOT ok
20Error on : 14 unable to open database file
finilized NOT ok
20Error on : 14 unable to open database file
finilized NOT ok
20Error on : 14 unable to open database file
finilized NOT ok

我用lsof和htop检查了我的运行过程,找出它打开的文件和内存泄漏。 谢谢你的帮助

2 个答案:

答案 0 :(得分:2)

您的代码的以下片段看起来很可疑,因为在没有介入关闭的情况下进行多次公开调用。

rc = sqlite3_open(dbfilepath, &db);
//    if( rc )
while(sqlite3_open(dbfilepath, &db))
...

documentation声明如下:

  

打开时是否发生错误,资源相关联   应该通过传递它来释放数据库连接句柄   不再需要sqlite3_close()时。

答案 1 :(得分:0)

根据这个页面它是故意的。如果数据库发生了某些事情,则不会关闭文件句柄。 根据我的经验,如果不修改数据库,文件句柄将始终关闭。

http://sqlite.1065341.n5.nabble.com/sqlite3-close-doesn-t-release-always-the-file-handle-td14159.html