2

10 個のスレッドを生成し、各スレッドがデータベースを開き (すべてのスレッドに共通)、またはオープンに失敗した場合はデータベースを作成し ("Write-Ahead Log" オプションを使用)、データベースにテーブルを作成してから実行する単純なプログラムを作成しました。テーブルに一度に 1 つの行を追加する無限ループに入ります。プログラムが 5 分ごとに約 2 つのハンドルをリークすることがわかりました。Memory Verify というツールを試してみると、リークしたハンドルが SQLite3 ファイル ロックであることがわかりました (バージョン 3.7.13 の 34034 行)。 SQLiteまたは私がそれを使用する方法です。

SQLite3 をビルドするためのコンパイラ オプションを指定していないため、マルチスレッドとしてビルドされます。私の理解では、すべてのスレッドに独自の SQLite 接続があるため、マルチスレッドは正常に動作するはずです。

データベースを開くか作成するには、次のコードを使用します。

   bool Create()
   {
      int iFlags = 0;
      iFlags = iFlags | SQLITE_OPEN_READWRITE | SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_CREATE;
      return sqlite3_open_v2(dbName_sm.c_str(), &pHandle_m, iFlags, 0) == SQLITE_OK;
   }

   bool Open()
   {
      int iFlags = 0;
      iFlags = iFlags | SQLITE_OPEN_READWRITE | SQLITE_OPEN_NOMUTEX;
      return sqlite3_open_v2(dbName_sm.c_str(), &pHandle_m, iFlags, 0) == SQLITE_OK;
   }

すべてのスレッドのハード ループは、INSERT ステートメントの準備、ステップ、およびファイナライズを行う ExecuteQuery を呼び出します。

   bool ExecuteQuery(const std::string& statement)
   {
      bool res = Prepare(statement);
      if(!res)
      {
         return false;;
      }
      SQLiteStatus status = Step();
      Finalize();
      res = (ESuccess == status || EDatabaseDone == status);
      return res;
   }

   bool Prepare(const std::string& statement)
   {
      return sqlite3_prepare_v2(pHandle_m, statement.c_str(), -1, &pStmt_m, 0) == SQLITE_OK;
   }

   enum SQLiteStatus { ESuccess, EDatabaseDone, EDatabaseTimeout, EDatabaseError };
   SQLiteStatus Step()
   {
      int iRet = sqlite3_step(pStmt_m);
      if (iRet == SQLITE_DONE)
      {
         return EDatabaseDone;
      }
      else if (iRet == SQLITE_BUSY)
      {
         return EDatabaseTimeout;
      }
      else if (iRet != SQLITE_ROW)
      {
         return EDatabaseError;
      }
      return ESuccess;
   }

   bool Finalize()
   {
      int iRet = sqlite3_finalize(pStmt_m);
      pStmt_m = 0;
      return iRet == SQLITE_OK;
   }

私のコードに何か間違いがありますか、それとも SQLite の既知の問題ですか? 数日間グーグルで検索しようとしましたが、何も見つかりませんでした。

ご助力ありがとうございます。

よろしく、

アンドレア

PS WinXP 64 ビット PC でテストを実行していることを忘れていました。コンパイラは VS2010、アプリケーションは 32 ビットでコンパイルされ、SQLite バージョンは 3.7.13 です...

4

1 に答える 1

-1

これはリークを引き起こす可能性がある1つのケースであるため、すべてのsqlite3_stepの後にsqlite3_resetがあるかどうかを確認してください。sqlite3_prepareでステートメントを準備し、sqlite3_stepで実行した後は、常にsqlite3_resetでリセットする必要があります。

于 2013-02-19T10:13:39.640 に答える