SQLite Forum

sqlite3.dll is not returning control to my program
Login

sqlite3.dll is not returning control to my program

(1) By anonymous on 2021-11-17 20:53:37 [link] [source]

I am using C++17 in Visual Studio 2019, and utilizing the sqlite3.dll from sqlite-dll-win64-x64-3360000, using a debug build

I've been working on a video game for the last few weeks. Each time a new game is created, I open the same .db file, and I run a "CREATE TABLE world (tile_type INT)" query for the game world. For now, each table and .db file have had the same names. Lazily, I do not delete the previous .db file nor its tables, so sqlite3_exec() returns 1 since the table is already created, and sqlite3_errmsg prints out the appropriate message. 

As of today, sqlite3_errmsg is not returning control to my program. SQL code has remained the same for the last 2 weeks. When stepping through with a debugger, after sqlite3_errmsg( db ) is called, the debugger step arrow disappears, all the autos/locals/variables get grayed out, the CPU usage drops to 0, and the game freezes.

UPDATE: "DROP TABLE world IF EXISTS" also silently fails and control is not returned. The only way to fix this is to delete the .db file, or to restart the computer.

The relevant code is below:

rc = sqlite3_exec( db, query.c_str(), NULL, NULL, &dbError );

assert( db != nullptr );

if( rc == SQLITE_CORRUPT ) {
	std::cerr << "The DB is corrupt!" << '\n';
}

if( rc ) {																								
	std::cerr << "Error executing SQLite3 statement: " << sqlite3_errmsg( db ) << std::endl;  // <-- the program loses control here
	std::cerr << "QUERY " << query << std::endl;

	sqlite3_free( dbError );
}

For reference, this is called each time a new game is created:

int GameEngine::openDB( string saveName ) {
	string path = savePath + saveName + ".db";															
	rc = sqlite3_open( path.c_str(), &db );																
	if( rc ) {																							
		std::cerr << "Could not open the database: " << path << '\n';
		return 1;
	}
	
	return 0;
}

(2) By anonymous on 2021-11-17 21:09:45 in reply to 1 [link] [source]

Another update (sorry):

This happens even if I delete the .db file. SQLITE_ERROR is returned from sqlite3_exec().

The problem temporarily goes away if I restart VS2019

(5) By Larry Brasfield (larrybr) on 2021-11-17 23:55:28 in reply to 2 [source]

I do not see anything definitely wrong with what you have shown. This makes me think something you're doing not yet shown is wrong. It would be a tedious guessing game to venture all the ways you might be erring.

Instead, I created this silly little C++ish program: #include <iostream> #include <string> #include <assert.h> #include "sqlite3.h" // using std::cout; using std::cerr; using std::endl; using std::string; // int execCallback(void*,int nc,char** pzColValues, char** pzColNames){ cout << "Result row:" << endl; for( int ic = 0; ic < nc; ++ic ){ char * zValue = (pzColValues[ic])? pzColValues[ic] : "NULL"; cout << " " << pzColNames[ic] << ": " << zValue << endl; } return 0; } // int main(int an, char *ap[]){ if( an < 2 ){ cerr << "Usage: sdb_futz <dbName> [<query1> ...]" << endl; return 1; } string dbName(ap[1]); sqlite3 * db = 0; int rc = sqlite3_open( dbName.c_str(), &db ); if( rc != SQLITE_OK ){ cerr << "Cannot open " << dbName << " as DB." << endl; return 2; } int nFlubs = 0; for( int na = 2; na < an; ++na ){ char * zErr = 0; string query(ap[na]); cout << "Running query: " << query << endl; rc = sqlite3_exec(db, query.c_str(), execCallback, 0, & zErr); if( rc != SQLITE_OK ){ cerr << "Exec failed with error " << rc << " (" << (zErr? zErr : "?") << ")" << endl; ++nFlubs; sqlite3_free(zErr); } } rc = sqlite3_close(db); return ( rc == SQLITE_OK && nFlubs == 0 )? 0 : 2+nFlubs; } // . This is what I did to build it: REM Prior to this, get 64-bit sqlite3.dll, sqlite3.def and REM sqlite3.h downloaded and extracted to this directory. REM Then, in a shell setup for MSVC 64-bit build tools, run: lib /def:sqlite3.def /out:sqlite3.lib /machine:amd64 REM Next, create something like above source: emacs_edit sdb_futz.cpp REM Then build and run it: cl -DDEBUG -EHsc sdb_futz.cpp /link sqlite3.lib sdb_futz furd.sdb "create table Silly(why text)" sdb_futz furd.sdb "insert into Silly values ('No reason'),('Why am I silly?')" sdb_futz furd.sdb "select * from Silly" "select count(*) from Silly" .

This ran as I would expect, so I'll not bore anybody with output.

I propose that you figure out how your code and build differ from the above. You can replicate my build, then use DUMPBIN to examine our objects and image to perhaps discover if linkage or calling convention has gone awry. (Naming conventions should prevent such problems, but they may have been circumvented.)

Your observation, "problem temporarily goes away if I restart VS2019", is not much to go on. But it does suggest you are causing the dreaded C/C++ undefined behavior to occur, just as your other symptoms suggest. (Failure of return from a SQLite API means something fundamental is wrong.)

You may notice that my build does virtually nothing to establish DLL linkage or set calling conventions. You may want to try that among your other explorations.

If you are serious about getting help with your problem here, you will need to simplify your code and build to something others here can reasonably hope to replicate. The Visual Studio IDE is nice, but it hides a tremendous amount of detail in its project files.

Obviously, you are building something which plays poorly with the sqlite3.dll published by the SQLite project. Yet, as you can see, I can build something that plays well with that DLL with little trouble.

(6) By ddevienne on 2021-11-18 08:08:17 in reply to 5 [link] [source]

Hi Larry. [OT] Just curious, why use <code> instead of triple-backtick?

And you certainly didn't manually do the escaping by hand, too many of them.
So how did you do that escaping? I don't see a way to do that in the Forum UI.

(8) By Larry Brasfield (larrybr) on 2021-11-18 15:40:45 in reply to 6 [link] [source]

I have this in ~/.bash_aliases:

alias mdquote="perl -p -e 's/([\\[\\]\\\\\\<\\>*#])/\\\\\$1/g;'"

What you see posted is a misbegotten mishmash of that filter's output and some incremental back-edits.

(3) By RandomCoder on 2021-11-17 23:22:45 in reply to 1 [link] [source]

You mention using the DLL. How are you getting pointers to and calling those pointers? I wouldn't be surprised to see the stack is being corrupted due to different calling conventions.

Also, why are you using the DLL? If you're writing a C++ app, why not just use the amalgamation?

(7.1) By Larry Brasfield (larrybr) on 2021-11-18 15:40:13 edited from 7.0 in reply to 3 [link] [source]

Deleted

(4) By Keith Medcalf (kmedcalf) on 2021-11-17 23:25:13 in reply to 1 [link] [source]

The problem is most likely located in what you have changed lately. If nothing is changed, then nothing will change. As it worked yesterday, so to will it work tomorrow, for all values of today.

So, what did you change between when "it worked as expected" and when "it did not work as expected"?

(Hint: The most likely culprit is Microsoft Visual Studio ...)

(9) By anonymous on 2021-11-18 17:42:29 in reply to 4 [link] [source]

I figured out the problem. it _was_ visual studio. 

When I fire up the program in a debug build, sometimes, for an unknown reason the console needs me to press any key for the code to continue executing. It usually happens before the SFML window is created. This time it was happening on the first  SQL query execution.

My guess is the console sometimes gets stuck in the "press any key to close this window" trigger, and needs to be activated so the std::cerr message can be displayed, before executing the next lines of code (even though a new instance of the program is run so exiting the console is no longer an active option)