这是 MSVC 2010 中的错误还是我做错了什么?
Is it a bug in MSVC 2010 or I am doing something wrong?
考虑以下代码片段:
在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 包含 = "SELECT * FROM "sys.abcattbl" WHERE "abt_tnam" = '' AND "abt_ownr" = '';"
我正在使用 MSVC2010,令我惊讶的是,“*name”包含空字符串。第一次调用 "to_bytes()" 成功,因为我可以检查将要使用的查询。
我必须在第一次调用 "to_bytes()" 后做些什么吗?或者我只需要升级编译器?
不对,你做错了。
我现在实际上不知道 to_bytes
return 是什么,但我假设它是基于 std::basic_string
的类型,所以 std::string
和家族.
to_bytes
return 是该字符串实例的临时对象,因此当您调用 c_str()
时,您将获得一个指向字符串第一个字符的指针,该字符串之后将不再存在陈述结束。你基本上有未定义的行为,因为 name
是一个悬空指针并且你试图输出它。
您必须分配内存并将字符串复制到其中,或者直接使用std::string
,不会出现此类问题。
你调用sqlite3_prepare_v2
成功的原因是to_bytes
编辑的字符串return仍然存在。该字符串在语句结束时被销毁,因此当 res
被赋予 sqlite3_prepare_v2
的 return 值时。之前没有,因此调用成功,因为传递了指向字符串的有效指针。
尽管如此,请升级您的编译器。
考虑以下代码片段:
在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 包含 = "SELECT * FROM "sys.abcattbl" WHERE "abt_tnam" = '' AND "abt_ownr" = '';" 我正在使用 MSVC2010,令我惊讶的是,“*name”包含空字符串。第一次调用 "to_bytes()" 成功,因为我可以检查将要使用的查询。
我必须在第一次调用 "to_bytes()" 后做些什么吗?或者我只需要升级编译器?
不对,你做错了。
我现在实际上不知道 to_bytes
return 是什么,但我假设它是基于 std::basic_string
的类型,所以 std::string
和家族.
to_bytes
return 是该字符串实例的临时对象,因此当您调用 c_str()
时,您将获得一个指向字符串第一个字符的指针,该字符串之后将不再存在陈述结束。你基本上有未定义的行为,因为 name
是一个悬空指针并且你试图输出它。
您必须分配内存并将字符串复制到其中,或者直接使用std::string
,不会出现此类问题。
你调用sqlite3_prepare_v2
成功的原因是to_bytes
编辑的字符串return仍然存在。该字符串在语句结束时被销毁,因此当 res
被赋予 sqlite3_prepare_v2
的 return 值时。之前没有,因此调用成功,因为传递了指向字符串的有效指针。
尽管如此,请升级您的编译器。