crash - MySQL C++ Connector crashes my app at ResultSet->getString() -
it's me again asking noob c++ questions
i had major headaches making darn (sorry language) mysql c++ connector work. don't know if poorly written or something, experience yet i've never had trouble making work.
anyhow got connect , throw exceptions on failed connect/query me quite big thing :u :p . actual problem comes out of me obtaining result of query. regardless of application crashes :s
i used 32-bit installer , libmysql.dll/lib 32-bit mysql server (since i'm compiling 32-bit application figured right thing do)
here's code imagine i'm talking about
dbmanager.h
#ifndef dbmanager_h #define dbmanager_h #define cppconn_public_func #define cppconn_lib_build true #include <string> #include "mysql_connection.h" #include "mysql_driver.h" #include <cppconn/driver.h> #include <cppconn/exception.h> #include <cppconn/resultset.h> #include <cppconn/statement.h> #include <cppconn/prepared_statement.h> class dbmanager { public: static dbmanager* instance(); bool query(const char* query); void connect(const char* dbhost, unsigned short dbport, const char* dbuser, const char* dbpass, const char* dbname); bool validcredentials(const char* username, const char* password); void manageexception(sql::sqlexception &e); ~dbmanager(); protected: static dbmanager* pinstance; private: dbmanager() {}; dbmanager(dbmanager const&){}; dbmanager& operator=(dbmanager const&){}; sql::mysql::mysql_driver* driver; sql::connection *con; sql::preparedstatement *pstmt; sql::resultset *res; sql::statement *stmt; bool isconnected; }; #endif
and cpp file dbmanager.cpp
#include "dbmanager.h" dbmanager* dbmanager::pinstance = null; dbmanager* dbmanager::instance() { if (!pinstance) { pinstance = new dbmanager(); } return pinstance; } bool dbmanager::query(const char* query) { return true; } dbmanager::~dbmanager() { delete con; delete pstmt; delete res; delete stmt; } void dbmanager::manageexception(sql::sqlexception& e) { if (e.geterrorcode() != 0) { std::cout << "# err: sqlexception in " << __file__; std::cout << "(" << __function__ << ") on line " << __line__ << std::endl; std::cout << "# err: " << e.what(); std::cout << " (mysql error code: " << e.geterrorcode(); std::cout << ", sqlstate: " << e.getsqlstate() << " )" << std::endl; } } void dbmanager::connect(const char* dbhost, unsigned short dbport, const char* dbuser, const char* dbpass, const char* dbname) { try { driver = sql::mysql::get_mysql_driver_instance(); std::string conndsn = "tcp://" + std::string(dbhost) + ":3306"; con = driver->connect(conndsn, sql::sqlstring(dbuser), sql::sqlstring(dbpass)); con->setschema(sql::sqlstring(dbname)); isconnected = true; std::cout<<"database connection successul."<<std::endl; } catch(sql::sqlexception &e) { manageexception(e); isconnected = false; return; } } bool dbmanager::validcredentials(const char* username, const char* password) { bool cred = false; try { pstmt = con->preparestatement("select * account account_name=? limit 1"); // smart use of indexing pstmt->setstring(1, username); res = pstmt->executequery(); while(res->next()) { if (res->getstring("password") == password) { cred = true; } } } catch(sql::sqlexception &e) { manageexception(e); return false; } return cred; }
basically, compiles without problem, connects without problem, executes queries without problem, second try retrieve data breakpoint exception thrown in file "xutils.cpp". have no idea i'm doing wrong. i'm using debug libraries while compiling debug. hmm libmysql.dll should release since extracted server bundle, don't seem find source compile own.
i have no idea why crashes , burn :/
ps: don't mind no hashing of password, proof of concept me in way of ... getting work first, securing :u
ps: have boost libraries compiled , ready in project, if :u
edit: main function
bool serverrunning = true; int main(int argc, char** argv) { #ifdef _win32 std::string title = text("window title change"); setconsoletitle(title.c_str()); #endif; std::cout<<"loading configuration file..."<<std::endl<<std::endl; std::string path = boost::filesystem::path(boost::filesystem::current_path()).string(); path += "\\config.ini"; iniparser* config = new iniparser(path.c_str()); //minini // sockets data std::string listenip = config->getstring("network", "listenip", "127.0.0.1"); unsigned short listenport = config->getint("network", "listenport", 5000); // database data std::string dbhost = config->getstring("database", "host", "localhost"); std::string dbuser = config->getstring("database", "user", "root"); std::string dbpass = config->getstring("database", "password", ""); std::string dbname = config->getstring("database", "database", "authserv"); unsigned short dbport = config->getint("database", "post", 1000); // general settings int sessiontimeout = config->getint("settings", "sessiontimeout", 10); int maxclients = config->getint("settings", "maxclients", 10); int servertimeout = config->getint("settings", "gameservertimeout", 1); // begin initialization dbmanager::instance()->connect(dbhost.c_str(), dbport, dbuser.c_str(), dbpass.c_str(), dbname.c_str()); bool loginsuccess = dbmanager::instance()->validcredentials("username", "password"); char c; while (serverrunning) { std::cin>>c; if (c == 'q') { serverrunning = false; } } return 0; }
assuming password
field defined varchar
in database, cannot use getstring()
retrieve it. must instead use blob
function, getblob()
.
this how while
loop look:
while(res->next()) { std::istream * retrievedpassword_stream = res->getblob("password"); if (retrievedpassword_stream) { char pws[password_length+1]; // password_length defined elsewhere; or use other functions retrieve retrievedpassword_stream->getline(pws, password_length); std::string retrievedpassword(pws); // also, should handle case password length > password_length if (retrievedpassword == std::string(password)) { cred = true; } } }
side comments: note there other issues code.
- the statement handle must deleted, should
delete pstmt;
@ appropriate place invalidcredentials()
function (rather in destructor). (but, why use prepared statement in case anyways? better initialize prepared statement in constructor (or somewhere else outside function query called), delete in destructor or elsewhere, if do use prepared statement. instead of prepared statement, though, note prepared statements useful high-use , high-cpu intensive queries, using password validation might not important here (you execute regular query, instead of prepared statement).) - likewise, resultset needs deleted (
delete res
) @ end of try block, rather in destructor. - be sure check null before using
pstmt
,res
, orcon
. stmt
appears unused , should not deleted.
Comments
Post a Comment