What is segmentation fault in C++ mysql? - c++

I am using C++ to send MySQL commands to a server. Why does it say "Segmentation fault" and what does it mean?
The output of the program when I run it is:
connection Succeeded
Segmentation fault
Edited the code to remove the i+1 line but still having same problem
the code:
#include <stdlib.h>
#include <iostream>
#include <mysql.h>
#include <stdio.h>
#define SERVER "localhost"
#define USER "root"
#define PASSWORD "coursework"
int main()
{
MYSQL *connect;
connect=mysql_init(NULL);
if (!connect)
{
std::cout<<"MySQL Initialization failed";
return 1;
}
connect=mysql_real_connect(connect, SERVER, USER, PASSWORD, NULL ,0,NULL,0);
if (connect)
{
std::cout<<"connection Succeeded\n";
}
else
{
std::cout<<"connection failed\n";
exit(1);
}
mysql_query (connect, "drop database if exists TTU;");
mysql_query (connect,"create database TTU;");
mysql_query (connect, "use TTU;");
mysql_query (connect, "create table students(tnumber char(8) PRIMARY KEY,");
mysql_query (connect, "firstname varchar(20) NOT NULL,");
mysql_query (connect, "lastname varchar(20) NOT NULL,");
mysql_query (connect, "dateofbirth date,");
mysql_query (connect, "INDEX 'lastname_i' ('lastname'),");
mysql_query (connect, "ENGINE=INNODB);");
mysql_query (connect, "insert into students(tnumber, firstname, lastname, dateofbirth)");
mysql_query (connect, "values (00001234, Joe, Smith, 1950-08-12);");
MYSQL_RES *res_set;
MYSQL_ROW row;
mysql_query (connect,"select * from students;");
unsigned int i =0;
res_set = mysql_store_result(connect);
unsigned int numrows = mysql_num_rows(res_set);
while ((row= mysql_fetch_row(res_set)) != NULL )
{
std::cout << row[i] << std::endl;
}
mysql_close (connect);
std::cout << "TEST" << std::endl;
return 0;
}

There are multiple bugs in the shown code. There are two major bugs: Incorrect usage of mysql_query(), and repeated failures to check the return value from various MySQL library functions, resulting in a failure to detect various errors.
mysql_query (connect, "create table students(tnumber char(8) PRIMARY KEY,");
This is not valid SQL. mysql_query() takes a complete SQL statement and executes it. It doesn't take individual fragments of an SQL statement, broken down across multiple consecutive invocations, and only executes it once a complete SQL statement gets parsed.
Because the shown code fails to check the return value from mysql_query(), it fails to detect that this whole sequence of mysql_query() calls have failed, and the table did not get created.
Subsequent call also fails to check the return value from other MySQL library functions.
The shown code is likely getting a NULL back from mysql_store_result(), fails to check for it, passes a NULL pointer to mysql_num_rows(), and crashes.

Related

Random Segmentation Fault - Raspberry Pi, C++, MySQL

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

Qt 5.4, database not open error

I'm new to C++/Qt and am trying to write to a SQLite database that I have created in the root directory of my project.
Here is one of the many sites I've been using for reference:
http://www.java2s.com/Code/Cpp/Qt/ConnecttoSqliteanddoinsertdeleteupdateandselect.htm
I created a function that receives an argument of all the user entered values as an object. I would like to write these values that the user entered into my root directory database.
Here is the function that takes the database object and attempts to write them into my root level database "matrixics.db".
My Function:
#include <QtSql>
#include <QSqlDatabase>
#include <QtDebug>
#include <QFile>
#include <QMessageBox>
void db_connection::writeDBValues(db_config *dbInfo)
{
//connect to matrixics.db
QSqlDatabase matrixics = QSqlDatabase::addDatabase("QSQLITE", "MatrixICS");
//using absolute path doesn't work either
//matrixics.setDatabaseName("D:/Qt Projects/build-MatrixICS-Desktop_Qt_5_4_0_MinGW_32bit-Debug/matrixics.db");
matrixics.setDatabaseName("./matrixics.db");
if(!QFile::exists("./matrixics.db"))
{
QString failedMsg = tr("FAILED: Could not locate matrixics.db file");
QMessageBox::warning(this, tr("ERROR: Failed MatrixICS Database Connection!"), failedMsg);
}
else if (!matrixics.open())
{
QString failedMsg = tr("FAILED: ") + matrixics.lastError().text();
QMessageBox::warning(this, tr("ERROR: Failed to open matrixics.db!"), failedMsg);
}
else
{
//write db values
QSqlQuery qry;
if (m_connectionName == "localDb")
{
qry.prepare( "INSERT INTO settings (local_db_type, local_db_host, local_db_port, local_db_user, local_db_pass) VALUES (?, ?, ?, ?, ?)" );
}
else if (m_connectionName == "remoteDb")
{
qry.prepare( "INSERT INTO settings (remote_db_type, remote_db_host, remote_db_port, remote_db_user, remote_db_pass) VALUES (?, ?, ?, ?, ?)" );
}
//bind all values
qry.addBindValue(dbInfo->m_db_type);
qry.addBindValue(dbInfo->m_hostname);
qry.addBindValue(dbInfo->m_port);
qry.addBindValue(dbInfo->m_db_user);
//encode user pass
//base64_encode is included in a globals.h fn not shown above
QString encodedPass = base64_encode(dbInfo->m_db_pass);
qry.addBindValue(encodedPass);
if(!qry.exec()) qDebug() << qry.lastError();
matrixics.close();
}
QSqlDatabase::removeDatabase("MatrixICS");
}
The Error:
QSqlQuery::prepare: database not open
QSqlError("", "Driver not loaded", "Driver not loaded")
QSqlDatabasePrivate::removeDatabase: connection 'MatrixICS' is still in use, all queries will cease to work.
My Question:
How is it possible for the script to make it down to the QSqlQuery::prepare function without the database being open? I would think that when I perform if (!matrixics.open()) the script would throw my "Failed to open" message if the database was not open. However, it is not, so logic should dictate that the database is in fact open, yet I receive QSqlQuery::prepare: database not open.
Your QSqlQuery object must be constructed with a reference to the QSqlDatabase. In other words, make that line
QSqlQuery qry(matrixics);
See QSqlQuery::QSqlQuery documentation.

How to get data from intersystems cache db through ODBC?

This is how i try to get a data from db:
#include <QCoreApplication>
#include <QtCore>
#include <QtSql>
#include "iostream"
int main(int argc, char *argv[])
{
QSqlDatabase db = QSqlDatabase::addDatabase("QODBC");
db.setDatabaseName("DRIVER={InterSystems ODBC};SERVER=localhost;PORT=1972;DATABASE=USER;UID=_system;PWD=SYS; Unicode SQLTypes=1;");
if (!db.open())
{
std::cout << "Error opening database" << std::endl;
return -1;
}
else
{
QSqlQuery query;
if(query.exec("SELECT * FROM ACCOUNTS")){
std::cout << "Select succses!" << std::endl;
}
while (query.next())
{
std::cout << "Getting results..." << std::endl;
std::cout << query.value(0).toString().toStdString() << std::endl;
}
std::cout << "EXIT!" << std::endl;
return 0;
}
}
And after query.exec(...) query.next() is always false but I really know that there is a data in the table. This behavior reproduce in the case when I try to get data from sample tables of Cache DB. What did i do wrong?
Thanks for your help.
The problem was that connection config is wrong:
QSqlDatabase db = QSqlDatabase::addDatabase("QODBC");
db.setDatabaseName("DRIVER={InterSystems ODBC};SERVER=localhost;PORT=1972;DATABASE=USER;UID=_system;PWD=SYS; Unicode SQLTypes=1;");
it should be:
QSqlDatabase db = QSqlDatabase::addDatabase("QODBC3");
db.setDatabaseName("DRIVER={InterSystems ODBC35};SERVER=localhost;PORT=1972;DATABASE=USER;UID=_system;PWD=SYS; Unicode SQLTypes=1;");
[as I said in the comments, I'm not familiar with this API Just looking through the documentation as I answer]
the documentation for the constructor of QSqlQuery
Constructs a QSqlQuery object using the SQL query and the database db.
If db is not specified, or is invalid, the application's default
database is used. If query is not an empty string, it will be
executed.
This means your query is opened on the default database (whatever that means).
Looking at the QSqlDatabase documentation:
QSqlDatabase also supports the concept of a default connection, which
is the unnamed connection. To create the default connection, don't
pass the connection name argument when you call addDatabase().
however, you're giving a name argument in your addDatabase():
QSqlDatabase db = QSqlDatabase::addDatabase("QODBC");
... that means it is not the default connection.
My guess is that you should either:
QSqlDatabase db = QSqlDatabase::addDatabase();
or
QSqlQuery query=QSqlQuery(db);

libmysqlclient.18.dylib memory leak

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.

Process utf-8 data from MySQL in C++ and give result back

I just simply want to know - how to get MySQL results to C++ in string (or another similar "string" datatype) in a way that would not deform data saved in utf8_unicode_ci.
After C++ process, app should write results back (to another table) into the database where argument is encoded in utf8_unicode_ci as well.
I read somewhere that using wide char is not recommended by Unicode consortium, but my problem is still that a second argument for mysql_query() is string which is not wide enough.
I've already tried some "utf8 string" solutions, but unsuccessfully. I also tried to save data in common string and than write it into the database in the same way (byte after byte), but it doesn't work properly at all... (see my code below)
DATABASE:
save_text: text = ěščřžýáíé
AFTER PROCESS: save_newtext: text = ?š??žýáíé
#include <iostream>
#include <mysql.h>
#include <string>
#define ... // server conection
using namespace std;
MYSQL *connection, mysql;
MYSQL_RES *result;
MYSQL_ROW row;
int query_state;
int main(int argc, char** argv)
{
mysql_init(&mysql);
mysql_real_connect(&mysql,CTH_SERVER,CTH_USER,CTH_PASSWORD,CTH_DB_IN,0,0,0));
mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, "utf8");
mysql_options(&mysql, MYSQL_INIT_COMMAND, "SET NAMES utf8");
mysql_query(connection, "SELECT text FROM save_text WHERE id = 23");
result = mysql_store_result(connection);
if ((row = mysql_fetch_row(result)) != NULL) {
string sql;
sql = "INSERT INTO save_newtext (text) VALUES ('";
sql += row[0];
sql += "')";
mysql_query(connection, sql.c_str());
}
return 0;
}
Thanks in advance!!
From MySQL Reference
mysql_options() should be called after mysql_init() and before
mysql_connect() or mysql_real_connect().
So your code should be
mysql_init(&mysql);
mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, "utf8");
mysql_options(&mysql, MYSQL_INIT_COMMAND, "SET NAMES utf8");
mysql_real_connect(&mysql,CTH_SERVER,CTH_USER,CTH_PASSWORD,CTH_DB_IN,0,0,0));