次のコードスニペットを検討してください。
database_sqlite.h内:
class __declspec(dllexport) SQLiteDatabase : public Database
{
virtual void GetTableProperties(DatabaseTable *table, std::vector<std::wstring> &errorMsg);
protected:
struct SQLiteImpl;
};
struct SQLiteDatabase::SQLiteImpl
{
std::wstring m_catalog;
std::wstring_convert<std::codecvt_utf8<wchar_t> > m_myconv;
};
database_sqlite.cpp:
void SQLiteDatabase::GetTableProperties(DatabaseTable *table, std::vector<std::wstring> &errorMsg)
{
sqlite3_stmt *stmt = NULL;
std::wstring errorMessage;
int result;
std::wstring query = L"SELECT * FROM \"sys.abcattbl\" WHERE \"abt_tnam\" = ? AND \"abt_ownr\" = ?;";
const unsigned char *dataFontName, *headingFontName, *labelFontName;
int res = sqlite3_prepare_v2( m_db, sqlite_pimpl->m_myconv.to_bytes( query.c_str() ).c_str(), (int) query.length(), &stmt, 0 );
if( res == SQLITE_OK )
{
const char *name = sqlite_pimpl->m_myconv.to_bytes( table->GetTableName().c_str() ).c_str(); // I used this line for debugging purposes
res = sqlite3_bind_text( stmt, 1, sqlite_pimpl->m_myconv.to_bytes( table->GetTableName().c_str() ).c_str(), -1, SQLITE_STATIC );
if( res == SQLITE_OK )
{
res = sqlite3_bind_text( stmt, 2, sqlite_pimpl->m_myconv.to_bytes( table->GetSchemaName().c_str() ).c_str(), -1, SQLITE_STATIC );
if( res == SQLITE_OK )
{
while( true )
{
char * result_query = sqlite3_expanded_sql(stmt); res = sqlite3_step(stmt);
ここで、* result_query contains = "SELECT * FROM" sys.abcattbl "WHERE" abt_tnam "= '' AND" abt_ownr "= '';" 私はMSVC2010を使用していますが、驚いたことに、「* name」には空の文字列が含まれています。使用されるクエリを確認できるため、「to_bytes()」の最初の呼び出しは成功しました。
「to_bytes()」を最初に呼び出した後、何かする必要がありますか?または、コンパイラをアップグレードする必要がありますか?
いいえ、あなたは何か間違ったことをしています。
私は実際に何to_bytes
が返されるかはわかりませんが、それはstd::basic_string
、sostd::string
とfamilyのタイプベースであると想定します。
to_bytes
はその文字列インスタンスへの一時オブジェクトを返すため、を呼び出すとc_str()
、ステートメントの終了後に存在しなくなる文字列の最初の文字へのポインタを取得します。name
ダングリングポインタであり、それを出力しようとしているため、基本的に未定義の動作があります。
メモリを割り当てて文字列をコピーするか、または単にを使用するstd::string
必要があります。この場合、問題のタイプは発生しません。
呼び出しがsqlite3_prepare_v2
成功する理由は、によって返される文字列がto_bytes
まだ存在するためです。文字列はステートメントが終了すると破棄されるためres
、の戻り値はsqlite3_prepare_v2
。に割り当てられます。文字列への有効なポインタが渡されるため、以前ではなく、したがって呼び出しは成功します。
それでも、コンパイラをアップグレードしてください。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加