首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

SQLite3 記憶體洩漏陷阱:忘記釋放錯誤訊息緩衝區導致 40 bytes 洩漏

     編輯:關於SqlServer

問題發現

程式進程記憶體洩漏檢測報告:

Detected memory leaks!
Dumping objects ->
{814} normal block at 0x0370AFD0, 40 bytes long.
Data: 74 61 62 6C 65 20 54 61 62 6C 65 5F 53 74 72 61  (table Table_Str)
Object dump complete.

洩漏內容正是建表 SQL 字串片段,提示與 sqlite3_exec 錯誤處理有關。

問題代碼

if (result == SQLITE_OK) {
    char *errmsg = NULL;
    int nError = sqlite3_exec(
        m_sqlite3DB,
        "create table Table_StrangeWords( ID integer primary key autoincrement, name nvarchar(32) ,)",
        NULL, NULL, &errmsg );
    if (nError != SQLITE_OK) {
        ATLTRACE("建立表失敗,錯誤碼:%d,錯誤原因:%s\n", result, errmsg);
    }
    // 缺少釋放 errmsg!
}

根本原因:SQLite 內部機制

追蹤 SQLite 原始碼(sqlite3_exec → sqlite3ApiExit):

if (rc != SQLITE_OK && rc == sqlite3_errcode(db) && pzErrMsg) {
    int nErrMsg = 1 + strlen(sqlite3_errmsg(db));
    *pzErrMsg = sqlite3_malloc(nErrMsg);  // 內部分配緩衝區
    if (*pzErrMsg) {
        memcpy(*pzErrMsg, sqlite3_errmsg(db), nErrMsg);
    }
}

關鍵點:SQLite 以 sqlite3_malloc 分配錯誤訊息緩衡區,**呼叫端負責釋放**,且**必須用 sqlite3_free**,不能用 delete 或 free。

修正代碼

if (result == SQLITE_OK) {
    char *errmsg = NULL;
    int nError = sqlite3_exec(
        m_sqlite3DB,
        "create table Table_StrangeWords( ID integer primary key autoincrement, name nvarchar(32) ,)",
        NULL, NULL, &errmsg );
    if (nError != SQLITE_OK) {
        ATLTRACE("建立表失敗,錯誤碼:%d,錯誤原因:%s\n", result, errmsg);
    }
    // 正確釋放
    if (errmsg != NULL) {
        sqlite3_free(errmsg);  // 必須用 sqlite3_free
    }
}

核心原則

  • SQLite 將記憶體管理封裝,**所有 sqlite3_malloc/sqlite3_realloc 分配的記憶體,必須配對 sqlite3_free 釋放**
  • 錯誤訊息指標 errmsg 即使執行成功(SQLITE_OK)也可能被分配(視版本),統一在最後檢查並釋放
  • 遇到洩漏優先查閱 SQLite 原始碼,確認分配/釋放配對關係

延伸提醒

同樣適用於 sqlite3_get_table、sqlite3_prepare 等回傳緩衝區的 API。養成「用完即釋、成對出現」習慣,避免 C/C++ 手動記憶體管理陷阱。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved