The problem appears to be the use of ostringstream to generate and contain the identifier string. Here's the code:
std::ostringstream blid;
blid << ...
sqlite3_bind_text(pStmt, 1, blid.str().c_str(), blid.str().length(), nullptr);
The str() method returns a temporary copy of ostringstream's internal string object and that copy is destroyed after the statement in which it it used. So it looks like the bind call is retaining the string pointer until a later statement, probably the step call, at which point the temporary has been destroyed.
The tricky point is that this code worked for short identifiers up to 15 bytes and that can be explained if the string object contains a special 16 byte array to store short strings and it survives uncorrupted long enough for the code to work with short strings.
The solution is to keep a copy of the identifier long enough for SQLite to finish with it. Something like:
std::ostringstream idBuf;
idBuf << ...
std::string blid = idBuf.str();
sqlite3_bind_text(pStmt, 1, blid.str().c_str(), blid.str().length(), nullptr);
...
int rc = sqlite3_step(pStmt);
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…