I'm having an issue with segmentation faults crashing my c++ program. I've narrowed it down to executing mysql queries. If I remove the query it never crashes but when it does run the query it may work 5 times in a row and crash or it might go 20 times before a segmentation fault, it's very random.
This is the code to connect.
MYSQL *conn;
void connectMysql(){
const char *server = "localhost";
const char *user = "root";
const char *password = "myPpassword";
const char *database = "myDatabase";
conn = mysql_init(NULL);
/* Connect to database */
if (!mysql_real_connect(conn, server,
user, password, database, 0, NULL, 0)) {
fprintf(stderr, "%s\n", mysql_error(conn));
exit(1);
}
}
Then I do this to run my queries. It'll happen with other queries as well.
connectMysql();
std::string query = "UPDATE settings SET tempFormat = '" + to_string(tempFormat) + "'";
std::cout << query << std::endl; // print string to terminal
mysql_query(conn, query.c_str());
std::cout << "done" << std::endl; // print done to terminal
mysql_close(conn);
Using std::cout to write to terminal it looks like it's happening with mysql_query function. I print the query string to terminal and that always looks good going into mysql_query even when it crashes. When it does crash I never see the "done" printed to terminal so it doesn't make it that far.
I've just recently discovered this as I don't save to database that often so not exactly sure what c++ mysql library I'm using but this is what I use to install it.
sudo apt-get install libmariadb-dev-compat libmariadb-dev -y
Thanks
Related
I'm new to databases and I wrote this practice program to test Berkeley BDB. I'm getting trouble opening the environment - the error appears in my console and says:
testEnv\_db.001: No such file or directory
Error opening database environment
DbEnv::open: No such file or directory
The code of the console program is based strongly off the examples in the Berkeley DB Transactions guide, and here's the text of the program up to the error, under int main().
String^ key_allkeys = "_ALLKEYS";
String^ key_valcount = "_COUNT";
// 1. Print some information to the screen, prompt user to enter path for key-value pair location:
Console::WriteLine("Oracle Berkeley DB Example Database Creator");
Console::WriteLine();
Console::WriteLine("Enter the path to the text file of key-value pairs:");
String^ kv_path = Console::ReadLine();
// 2. Declare initial variables:
String^ totalkeys;
int totalval;
// 3. Open the database:
u_int32_t env_flags = DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN;
std::string envHome("testEnv");
u_int32_t db_flags = DB_CREATE | DB_AUTO_COMMIT;
Db *dbp = NULL;
const char *file_name = "mydb.db";
DbEnv myEnv(0);
try
{
myEnv.open(envHome.c_str(), env_flags, 0);
dbp = new Db(&myEnv, 0);
dbp->open(NULL, file_name, NULL, DB_BTREE, db_flags, 0);
}
catch(DbException &e)
{
std::cerr << "Error opening database environment: " << std::endl;
std::cerr << e.what() << std::endl;
exc_block(); // Block
return (EXIT_FAILURE);
}
It should be fairly obvious that the program is failing right around the try/catch blocks. I've read the manual (literally RTFM) and I couldn't figure it out - the DB_CREATE flag is specified for both the environment and database, so there shouldn't be an issue here.
Any ideas?
It may simply be that the testEnv directory doesn't exist in the directory where you are running the program? You have to create the environment home directory yourself.
Also, you may wish to specify DB_RECOVER when opening the environment.
I've been trying to use the mysql++ library in my application (windows x64 based) but I can't seem to connect to my sql server.
Some information:
I used this code to connect to the server:
mysqlpp::Connection conn(db, 0, user, pass, 3306);
this definitely has the right data in it.
and then, my sql server is the standard service from the MySQL install. And I'm pretty sure I used the standard settings. I can connect to it using the MySql Workbench and I edited some new tables and such but my own program doesn't seem to connect.
I read the documentation and I can't find anything specific that might suggest something why I can't connect.
Oh, so many issues, so little time...
Have you checked that your program has permissions to access the database?
Does your program have the correct privileges?
Is your host name correct?
What errors are you getting?
What exception is thrown?
When you use the debugger, what line is the error on?
Here's my method:
sql::Connection * const
Manager ::
get_db_connection(void) const
{
//-------------------------------------------------------------------------
// Use only one connection until proven that more connections will make
// the program more efficient or have a beneficial impact on the user.
// Thus the change in returning sql::Connection * rather than a smart pointer.
// A smart pointer will delete its contents.
//-------------------------------------------------------------------------
static const char host_text[] = "tcp://127.0.0.1:3306/";
static std::string host_name;
if (!m_connection_initialized)
{
host_name = host_text;
initialize_db_driver();
host_name += m_dataset_info.m_dsn_name;
try
{
m_p_connection = m_p_sql_driver->connect(host_name.c_str(),
m_dataset_info.m_user_name.c_str(),
m_dataset_info.m_password.c_str());
}
catch (sql::SQLException &e)
{
/*
The MySQL Connector/C++ throws three different exceptions:
- sql::MethodNotImplementedException (derived from sql::SQLException)
- sql::InvalidArgumentException (derived from sql::SQLException)
- sql::SQLException (derived from std::runtime_error)
*/
wxString wx_text = wxT("# ERR: SQLException in ");
wx_text += wxT(__FILE__);
wxLogDebug(wx_text);
wx_text.Printf(wxT("# ERR: (%s) on line %d"),
__FUNCTION__,
__LINE__);
wxLogDebug(wx_text);
wx_text.Printf(wxT("# ERR: %s (MySQL error code: %d, SQLState: %s)"),
e.what(),
e.getErrorCode(),
e.getSQLState());
wxLogDebug(wx_text);
wxLogDebug(wxT("Verify that mysqlcppconn.dll is in the PATH or in the working directory."));
// throw Manager_Connection_Not_Initialized();
m_connection_initialized = false;
}
catch (...)
{
std::cout << "Unhandled database SQL exception\n" << flush;
m_connection_initialized = false;
}
m_connection_initialized = true;
}
return m_p_connection;
}
PROBLEM: What's the cause of the memory leaks?
SITUATION:
I've build a simple command line program using C++ together with MySQL using the MySQL C API
The problem is, the program has many "minor" memory leaks from the object malloc xx bytes" with xx ranging from a few bytes to 8 kb. All of the leaks links to the library libmysqlclient.18.dylib.
I've already removed all the mysql_free_result() from the code to see if that was the problem, but its still the same.
My MySQL code mainly consists of simple code like:
to connect:
MYSQL *databaseConnection()
{
// declarations
MYSQL *connection = mysql_init(NULL);
// connecting to database
if(!mysql_real_connect(connection,SERVER,USER,PASSWORD,DATABASE,0,NULL,0))
{
std::cout << "Connection error: " << mysql_error(connection) << std::endl;
}
return connection;
}
executing a query:
MYSQL_RES *getQuery(MYSQL *connection, std::string query)
{
// send the query to the database
if (mysql_query(connection, query.c_str()))
{
std::cout << "MySQL query error: " << mysql_error(connection);
exit(1);
}
return mysql_store_result(connection);
}
example of a query:
void resetTable(std::string table)
{
MYSQL *connection = databaseConnection();
MYSQL_RES *result;
std::string query = "truncate table " + table;
result = getQuery(connection, query);
mysql_close(connection);
}
First of all: Opening a new connection for every query (like you're doing in resetTable()) is incredibly wasteful. What you really want to do is open a single connection when the application starts, use that for everything (possibly by storing the connection in a global), and close it when you're done.
To answer your question, though: You need to call mysql_free_result() on result sets once you're done with them.
I am trying to run through a series of checks/inserts into a MySQL 5.5 db, but I am having frequent yet intermittent issues with SIGSEGV errors. Over the course of many queries being executed, the SELECT statements run just fine. However, after some variable amount of time or number of executed queries (sometimes thousands of checks, sometimes 1 or 2, sometimes not at all and the program exits normally), I inexplicably get a segfault...
Program received signal SIGSEGV, Segmentation fault.
0x100188a8 in mysql_send_query () from K:\Programming\C\Test\libmysql.dll
(gdb) bt full
#0 0x100188a8 in mysql_send_query () from K:\Programming\C\Test\libmysql.dll
No symbol table info available.
#1 0x100188e5 in mysql_real_query () from K:\Programming\C\Test\libmysql.dll
No symbol table info available.
#2 0x00000000 in ?? ()
No symbol table info available.
(gdb)
This is from my heavily reduced code:
int main() {
for (int i = 0; i < 5000; i++) {
int iNewX = GenerateRandomInt(1, 50);
int iNewY = GenerateRandomInt(1, 50);
std::string str = "SELECT * FROM Resources WHERE XPOS = ";
str = str +
StatToString(iNewX) + " AND YPOS = " +
StatToString(iNewY) + ";";
const char * Query = str.c_str();
MYSQL *connect;
connect=mysql_init(NULL);
connect=mysql_real_connect(connect,SERVER,USER,PASSWORD,DATABASE,0,NULL,0);
// Print SQL statment for debugging only...
// This appears to always be good, even in the case of the segfault.
std::cout << Query << std::endl;
if (mysql_query(connect, Query)) {
// Supposed to log an error; I don't get this far...
// This does work when I intentionally break the statement.
std::cout << printf("Failed to SELECT, Error: %s", mysql_error(connect));
std::cout << printf("Query: %s", Query) << std::endl;
mysql_close(connect);
return 0;
}
mysql_close(connect);
}
return 1;
}
I have been unsuccessful in searching online for a case that really matches what I have going on here (though there are lots of MySQL/segfault related forum/Q+A topics/threads). Since this appears to be happening within the .dll itself, how can I fix this?
Can anyone explain why the issue seems to come and go?
I have not yet tried to reinstall MySQL, as that will likely be a very big headache that I would rather avoid. If I must, then I must.
If I am missing any details in my question or any pertinent code, please let me know and I will add.
After following Christian.K's advice, I was able to see that this was error 23 (as returned by mysql_error(connect)) after connect=mysql_init(NULL).
This led me to a few resources, most clearly, this one. This says that this is a know problem when working within Windows, and there's not much I can do about this.
You might get around the open file limit (error 23) by not opening a connection for every loop iteration (which is questionable anyway), but rather use one connection for all loop iterations.
Together with my comments about error handling, and the strange cout << printf use you end up with something like this:
int main() {
MYSQL *connect;
connect=mysql_init(NULL);
if (connect == NULL)
{
printf("Insufficient memory to initialize.\n");
return 1;
}
connect=mysql_real_connect(connect,SERVER,USER,PASSWORD,DATABASE,0,NULL,0);
if (connect == NULL)
{
printf("Could not connect: %s\n", mysql_error(connect);
return 1;
}
for (int i = 0; i < 5000; i++) {
int iNewX = GenerateRandomInt(1, 50);
int iNewY = GenerateRandomInt(1, 50);
std::string str = "SELECT * FROM Resources WHERE XPOS = ";
str = str +
StatToString(iNewX) + " AND YPOS = " +
StatToString(iNewY) + ";";
const char * Query = str.c_str();
if (mysql_query(connect, Query)) {
// Supposed to log an error; I don't get this far...
// This does work when I intentionally break the statement.
printf("Failed to SELECT, Error: %s", mysql_error(connect));
printf("Query: %s", Query);
mysql_close(connect);
return 1;
}
}
mysql_close(connect);
return 0;
}
Note that I also changed the return values. Per convention main() should return 0 on success and something else (mostly 1) otherwise.
I've written a console app which receives events via boost::interprocess memory and dumps the info into an sqlite3 database. While running the app I've noticed that, in the Windows task manager, the memory usage was cyclically increasing every... 30s-1min. This led me to believe that the problem lies within the main loop in which I execute my SQL. I've added some monitoring and apparently the sqlite3_memory_usage returns increasing results every couple loop iterations.
Can somebody tell me what am I doing wrong? Am I missing something I should de-allocate ?
Here are 2 strings I use to generate SQL
const std::string sql_insert =
"INSERT INTO EventsLog "
"(Sec, uSec, DeviceId, PmuId, EventId, Error, Msg) "
"VALUES (%ld, %ld, %ld, %d, %ld, %d, %Q)";
const std::string sql_create =
"CREATE TABLE IF NOT EXISTS EventsLog("
"Id INTEGER PRIMARY KEY AUTOINCREMENT, "
"Sec INTEGER NOT NULL, "
"uSec INTEGER NOT NULL, "
"DeviceId INTEGER NOT NULL, "
"PmuId INTEGER NOT NULL, "
"EventId INTEGER NOT NULL, "
"Error INTEGER NOT NULL, "
"Msg TEXT"
")";
In here, I generate the SQL INSERT command
std::string construct_sql_query
(const ELMessageData & data)
{
std::string query = "";
ptime jan1st1970 = ptime(date(1970,1,1));
ptime now = boost::posix_time::microsec_clock::universal_time();
time_duration delta = now - jan1st1970;
TimeVal time((uint32)delta.total_seconds(),
(uint32)now.time_of_day().fractional_seconds());
char * const sql = sqlite3_mprintf(sql_insert.c_str(),
time.tv_sec,
time.tv_usec,
data.getDeviceId(),
data.getPmuId(),
data.getEventId(),
(data.getIsError() ? 1 : 0),
data.getExMsg().c_str());
if(sql == NULL)
post_event(EvIOError("Failed to create the SQL command",
"StLoggingEvents::_construct_sql_query"));
query = std::string(sql);
sqlite3_free(sql);
return query;
} // construct_sql_query
Here's the main loop in which I execute the INSERT commands
while(true)
{
m_exchange_obj->wait(); // wait for the semaphore to be raised
const std::string sql = construct_sql_query
(m_exchange_obj->receive());
char ** err = NULL;
const int rc = sqlite3_exec(m_db_handle,
sql.c_str(),
NULL,
NULL,
err);
sqlite3_free(err);
if(rc != SQLITE_OK)
{
LERR_ << "Error while inserting into the database";
LERR_ << "Last SQL Query : ";
LERR_ << sql;
}
else
{
LDBG_ << "Event logged...";
LDBG_ << "Sqlite3 memory usage : "
<< sqlite3_memory_used();
}
}
I second the suggestion of trying this under valgrind. You may also want to look at google's tcmalloc replacement... It can print pretty graphs showing you all your leaks... That said, I hope you get the answer for this... I plan on using SQLite in an upcoming project...
How are you determining your memory usage? You may not have a real leak.
If you are on a windows system and using visual studio, compile in debug mode and use the memory debugging macros to find your leaks.
If you are on a unix based system, try valgrind / memcheck.
I think OS X's xcode also detects leaks too.