0

アプリケーションを起動しようとしているときにこのエラーが発生しました。問題をコードのこの関数に切り分けましたが、なぜこれが起こっているのかわかりません...

void checkDB()
{
    sqlite3 *db;
    int rc=0;
    size_t i;
    char *zErrMsg = 0;

    HMODULE hModule = GetModuleHandleW(NULL);
    WCHAR path[MAX_PATH];
    char buffer[MAX_PATH*4];
    int len;
    GetModuleFileNameW(hModule, path, MAX_PATH);
    len =lstrlenW(path);
    path[len-13]='\0';
    buffer[0]='\0';

    wcscat_s(path,sizeof(path),L"test.db\0");
    GetFileAttributes(path);
    if(INVALID_FILE_ATTRIBUTES == GetFileAttributes(path) && GetLastError()==ERROR_FILE_NOT_FOUND)
    {
        wcstombs_s(&i,buffer,sizeof(buffer), path, wcslen(path) );
        rc= sqlite3_open(buffer,&db);

        rc=sqlite3_exec(db,"create table Recipe (Recipe_Num INTEGER PRIMARY KEY AUTOINCREMENT, Recipe_Image VARCHAR(30), Recipe_Name VARCHAR(200))",NULL,0,&zErrMsg);
        sqlite3_free(zErrMsg);
        rc=sqlite3_exec(db,"create table Recipe_Step (Recipe_Num INTEGER, Step_Num INTEGER, Description VARCHAR(2000))",NULL,0,&zErrMsg);
        if(rc!=SQLITE_OK)
        {
            sqlite3_close(db);
        }
        else
        {
        sqlite3_close(db);
        }
    }

}
4

1 に答える 1

1

char一部の生/WCHARバッファをオーバーランしている可能性はありますか?

コードを最新化し、生の配列や生の C 文字列関数の代わりに、またはのような堅牢な文字列クラスを使用することをお勧めします(これは誤用です:の代わりに渡す必要があります。「サイズ」はバイト単位ではなく、s 単位で表されます)。std::wstringCString[W]wcscat_s()_countof(path)sizeof(path)WCHAR

また、Unicode UTF-16 から ANSI/MBCS に変換するには、 の代わりにATL ヘルパーCW2Awcstombs_s()を使用できます。

例えば:

// Assume Unicode builds, so GetModuleFileName is actually GetModuleFileNameW,
// CString is CStringW, etc.

CString strPath;
WCHAR* pszPath = strPath.GetBuffer(MAX_PATH);
GetModuleFileName(hModule, pszPath, MAX_PATH);
// check GetModuleFileName()'s return value...
strPath.ReleaseBuffer();

// Operate on strPath using operator+= to concatenate strings, etc.
strPath += L"test.db";

....

if(INVALID_FILE_ATTRIBUTES == GetFileAttributes(strPath) && GetLastError()==ERROR_FILE_NOT_FOUND)
{
    // Convert from UTF-16 to ANSI
    CW2A buffer(strPath);
    rc = sqlite3_open(buffer, &db);
    ....

}

sqlite3_free(zErrMsg)さらに、の 2 回目の呼び出しの後に呼び出さないため、文字列メモリがリークしていますsqlite3_exec()。RAII パターンと C++ デストラクタの機能を使用して、リソースを自動的に解放するコードを作成することをお勧めします。sqlite3_free()これらの文字列に対して、デストラクタを呼び出す単純なラッパーを作成できます。たとえば、次のようになります。

class SqlLiteErrorMsg
{
public:   
    SqlLiteErrorMsg()
       : errorMsg(nullptr)
    {}

    ~SqlLiteErrorMsg()
    {
        sqlite3_free(errorMsg);
    }

    char** GetAddressOf()
    {
        return &errorMsg;
    }    

    char* Get()
    {
        return errorMsg;
    }

private:
    // Ban copy
    SqlLiteErrorMsg(const SqlLiteErrorMsg&);
    SqlLiteErrorMsg& operator=(const SqlLiteErrorMsg&);

    char* errorMsg;
};

sqlite3*同様のラッパーをポインターの周りに構築できます。

于 2013-03-28T19:13:02.397 に答える