编辑:感谢所有指出问题的人,并在 Stack Overflow 上进行了讨论。我自己投了最后一票。
一个相关的问题:CPP Reference 既不是临时的,ostringstream
也不ostringstream::str
是临时的。这么多人怎么知道的?或者是否有我应该查阅的不同文件?
我在使用 GCC 4.7.2 的 Debian 7.3 (x64)-std=c++11
和std::ostringstream
. 它导致了像https://stackoverflow.com/questions/21260815/which-r-in-this-create-table-error-message这样的结果。
完整的程序使用 Sqlite。从命令行与 Valgrind 运行简化案例会打印 2 个不同的错误。整个简化案例程序可在Code Viewer上找到(我认为在这里发布整个示例有点长)。它所做的只是初始化 Sqlite,打开数据库,创建表,关闭数据库,以及初始化数据库。如果发生错误,它会报告错误。没有其他事情发生。
这是简化案例程序的一部分,它只是尝试创建一个表。如果表存在,它应该产生一个错误(它确实):
ostringstream qs;
qs.str().reserve(96);
qs << "CREATE TABLE test";
qs << "(";
qs << " userid INTEGER PRIMARY KEY AUTOINCREMENT,";
qs << " username TEXT,";
qs << " salt BLOB,";
qs << " hmac BLOB";
qs << ");";
const char* stmt = qs.str().c_str();
AC_ASSERT(NULL != stmt);
rc = sqlite3_exec(db, stmt, NULL, NULL, &err);
AC_ASSERT(rc == SQLITE_OK);
if(rc != SQLITE_OK)
{
ostringstream oss;
oss.str().reserve(96);
oss << "sqlite3_exec failed, error " << rc;
LogError(oss.str().c_str());
oss.clear(), oss.str("");
oss << "Sqlite error: " << err;
LogError(oss.str().c_str());
// Break, handle error
}
但是,在命令行下,消息是:
sqlite3_exec failed, error 1
Sqlite error: table
在 Valgrind 下,消息是:
sqlite3_exec failed, error 1
Sqlite error: table test already exists
该程序大量使用ostringstream
.Valgrind 围绕它们产生了近 13 个问题,其中 9 个涉及operator delete(void*)
底层basic_string
. 例如,下面显示了一个(第 76 行来自t.cpp
is const char* stmt = qs.str().c_str();
):
==14318== Invalid read of size 1
==14318== at 0x45ACC8: sqlite3_exec (sqlite3.c:94542)
==14318== by 0x405D07: main (t.cpp:79)
==14318== Address 0x5d89728 is 24 bytes inside a block of size 127 free'd
==14318== at 0x4C27870: operator delete(void*) (vg_replace_malloc.c:502)
==14318== by 0x530EB1F: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.17)
==14318== by 0x405CF1: main (t.cpp:76)
有人对这里发生的事情有任何想法吗?是ostringstream
吗?或者也许是 GCC 4.7.2?或者也许是 Debian 的端口?
(对于开放式问题,我很抱歉。我已经无事可做)。