I am trying to query a database using the libmysql++ API and so far I am able to successfully run some queries. (reason behind some will be explained later)
So everything works fine, but as soon as I attempt at closing the connection and exiting the program, a Segmentation fault (core dumped) appears, as you can see below:
shell> g++ -o test testCDB.cpp -L/usr/include/mysql -lmysqlclient -I/usr/include/mysql
testCDB.cpp: In function ‘int main(int, char**)’:
testCDB.cpp:122:74: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
StudentManager manager1("localhost", "root", "ikilledkennedy.", "testDB");
^
testCDB.cpp:122:74: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
testCDB.cpp:122:74: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
testCDB.cpp:122:74: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
shell> ./test
Successfully connected to the database.
Enter your query: SHOW DATABASES;
[information_schema]
[mysql]
[performance_schema]
[sys]
[testDB]
Do you wish to continue?(Y:1/N:0) : 1
Enter your query: SHOW TABLES;
[Student]
Do you wish to continue?(Y:1/N:0) : 0
Segmentation fault (core dumped)
shell>
What's causing this issue and what measures do I take to resolve this?
Coming to the some queries part--there are certain queries that exit with a Segmentation fault too when fed to the database (like INSERT) which I feel is because these queries don't produce a result set and when I try to fetch rows in displayTable() or perhaps free the result set in performQuery(char *), a NULL value is encountered. Am I right in thinking this or is there some other root cause?
The code is as follows:
#include <iostream>
#include <string>
#include <mysql.h>
#include <limits>
using namespace std;
class StudentManager
{
private:
char *host;
char *user;
char *password;
char *database;
MYSQL *connection;
MYSQL_RES *result;
void init()
{
connection = mysql_init(NULL);
if(!mysql_real_connect(connection, host, user, password, database, 0, NULL, 0))
{
cout << "Cannot connect to the database.\n"
<< "Please make sure you have entered the details correctly and try again."
<< endl;
}
else
{
cout << "Successfully connected to the database.\n"
<< endl;
}
}
void displayTable()
{
MYSQL_ROW row;
unsigned int num_fields;
unsigned int i;
num_fields = mysql_num_fields(result);
cout << endl;
while((row = mysql_fetch_row(result)))
{
for(i = 0; i < num_fields; i++)
{
cout << "[" << ( row[i] ? row[i] : "NULL" ) << "]";
}
cout << endl;
}
cout << endl;
}
public:
StudentManager(char *host, char *user, char *password, char *database)
{
this->host = host;
this->user = user;
this->password = password;
this->database = database;
init();
}
void performQuery(char *query)
{
if(mysql_query(connection, query))
{
cout << "Query error: "
<< mysql_error(connection)
<< endl;
return;
}
result = mysql_use_result(connection);
displayTable();
mysql_free_result(result);
}
void disconnect()
{
cout << "Closing connection...";
mysql_close(connection);
cout << "Connection successfully closed.";
}
};
int main(int argc, char *argv[])
{
StudentManager manager1("localhost", "foo", "bar", "testDB");
int choice = 1;
char *query;
while(1)
{
cout << "Enter your query: ";
cin.getline(query, 256);
manager1.performQuery(query);
cout << "Do you wish to continue?(Y:1/N:0) : ";
cin >> choice;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
if(choice < 1)
{
manager1.disconnect();
break;
}
}
return 0;
}
char*withstd::string. Chances are that the problem will "magically" disappear, as will the warnings. And please don't write Java-style constructors in C++. Use initialisation lists.