I have a simple program that should print today's day name. It was working, but I made the get_query_result function and after that, it is giving me a segmentation fault.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mysql.h>
#define QUERY_SIZE 1000
void finish_with_error(MYSQL* con)
{
fprintf(stderr, "%s\n", mysql_error(con));
mysql_close(con);
exit(1);
}
void get_query_result(MYSQL *con, MYSQL_RES *result, char *query)
{
if(mysql_query(con, query))
{
finish_with_error(con);
}
result = mysql_store_result(con);
if(result == NULL)
{
finish_with_error(con);
}
}
int main()
{
MYSQL *con = mysql_init(NULL);
MYSQL_RES *result;
MYSQL_ROW row;
if(con == NULL)
{
fprintf(stderr, "mysql_init() failed\n");
exit(1);
}
if(mysql_real_connect(con, "127.0.0.1", "root", "mysqlpassword", "database", 0, NULL, 0) == NULL)
{
finish_with_error(con);
}
get_query_result(con, result, "SELECT DAYNAME(DATE(NOW()))");
row = mysql_fetch_row(result);
printf("%s\n", row[0]);
mysql_free_result(result);
return 0;
}
result in main is not affected by get_query_result, in consequence, you end up calling mysql_free_result with an uninitialized pointer.
Switch to
MYSQL_RES *get_query_result(MYSQL *con, char *query)
{
MYSQL_RES *result;
if(mysql_query(con, query))
{
finish_with_error(con);
}
result = mysql_store_result(con);
if(result == NULL)
{
finish_with_error(con);
}
return result;
}
and call it like:
result = get_query_result(con, "SELECT DAYNAME(DATE(NOW()))");
Related
Consider the following reproducer:
#include <wget.h>
#include <string.h>
#include <mysql.h>
MYSQL *mysql_con;
void
mysql_stop()
{
mysql_close(mysql_con);
}
void
mysql_start()
{
mysql_con = mysql_init(NULL);
if (mysql_con == NULL)
{
fprintf(stderr, "%s\n", mysql_error(mysql_con));
exit(1);
}
if (mysql_real_connect(mysql_con, "localhost", "crawler", "password", "crawl", 0, NULL, 0) == NULL)
{
fprintf(stderr, "%s\n", mysql_error(mysql_con));
exit(EXIT_FAILURE);
}
}
const char * parseURI (char *base_url, char *url)
{
wget_iri *base = wget_iri_parse(base_url, NULL);
wget_buffer *buf = wget_buffer_alloc(8192);
const char *uri = wget_iri_relative_to_abs(base, url, strlen(url), buf);
wget_buffer_free(&buf);
wget_iri_free(&base);
return uri;
}
void crawler_init()
{
const char *url2 = parseURI("http://www.google.com/", "/intl/en/policies/privacy/");
printf("%s\n", url2);
}
int main (int argc, char **argv)
{
const char *url2 = parseURI("http://www.google.com/", "/intl/en/policies/privacy/");
printf("%s\n", url2);
mysql_start();
crawler_init();
mysql_stop();
}
The output from running this program is:
http://www.google.com/intl/en/policies/privacy/
��7�
The first printf in main is printing out the absolute url as expected.
The second printf in crawler_init is printing out garbage instead of the same absolute url.
This appears to be related to mysql_real_connect as when this call is commented out the second printf in crawler_init prints out the expected absolute url.
Why?
Adding buf->data = NULL; fixes this:
#include <wget.h>
#include <string.h>
#include <mysql.h>
MYSQL *mysql_con;
void
mysql_stop()
{
mysql_close(mysql_con);
}
void
mysql_start()
{
mysql_con = mysql_init(NULL);
if (mysql_con == NULL)
{
fprintf(stderr, "%s\n", mysql_error(mysql_con));
exit(1);
}
if (mysql_real_connect(mysql_con, "localhost", "crawler", "1q2w3e4r", "crawl", 0, NULL, 0) == NULL)
{
fprintf(stderr, "%s\n", mysql_error(mysql_con));
exit(EXIT_FAILURE);
}
}
const char * parseURI (char *base_url, char *url)
{
wget_iri *base = wget_iri_parse(base_url, NULL);
wget_buffer *buf = wget_buffer_alloc(8192);
const char *uri = wget_iri_relative_to_abs(base, url, strlen(url), buf);
buf->data = NULL;
wget_buffer_free(&buf);
wget_iri_free(&base);
return uri;
}
void crawler_init()
{
const char *url2 = parseURI("http://www.google.com/", "/intl/en/policies/privacy/");
printf("%s\n", url2);
}
int main (int argc, char **argv)
{
const char *url2 = parseURI("http://www.google.com/", "/intl/en/policies/privacy/");
printf("%s\n", url2);
mysql_start();
crawler_init();
mysql_stop();
}
I have tried to connect to mysql server from C code.
#include <mysql.h>
#include <stdio.h>
#include <stdlib.h>
main(){
MYSQL *conn;
MYSQL_RES *res;
MYSQL_ROW row;
char *server = "localhost";
char *user = "root";
char *password = "12345"; /* set me first */
char *database = "mydatabase";
conn = mysql_init(NULL);
printf("done 1\n");
if (!mysql_real_connect(conn, server,
user, password, database, 3306, "/tmp/mysql.sock", 0)) {
fprintf(stderr, "%s\n", mysql_error(conn));
exit(1);
}
printf("done 2\n");
if (mysql_query(conn, "show tables")) {
fprintf(stderr, "%s\n", mysql_error(conn));
exit(1);
}
printf("done 3\n");
res = mysql_use_result(conn);
printf("done 4\n");
printf("MySQL Tables in mysql database:\n");
while ((row = mysql_fetch_row(res)) != NULL)
printf("%s \n", row[0]);
printf("done 5\n");
mysql_free_result(res);
mysql_close(conn);
}
But I have this weird problem:
done 1
Plugin caching_sha2_password could not be loaded: /usr//usr/lib/mysql/plugin/caching_sha2_password.so: cannot open shared object file: No such file or directory
I do not know why it tries to load lib from /usr//usr/
Please help if you have a deal with it already!
I called mysql_select_db() and it returned no errors, but when I called mysql_query() I got the following error:
No database selected.
I found a parameter of MYSQL struct. It is some char* calls db. What does it represent?
mysql_select_db() does changes this parameter?
Thanks.
Edit:
My main():
#include t-mysql.h
...
T_MYSQL *db = (T_MYSQL*) malloc(sizeof(T_MYSQL));
strcpy(db->database_name,mysql_database_name);
strcpy(db->password,mysql_password);
strcpy(db->root_password,mysql_root_password);
strcpy(db->server,mysql_server);
strcpy(db->table_name,mysql_table_name);
strcpy(db->user,mysql_user);
strcpy(db->query_create_db,query_create_db);
strcpy(db->query_create_table,query_create_table);
t_mysql_init(db);
t_mysql_connect(db);
t_mysql_createdb(db);
t_mysql_setdb(db);
t_mysql_createtable(db);
...
t-mysql.h:
#include <stdio.h>
#include <mysql.h>
#include <my_global.h>
#ifndef T_MYSQL_H_
#define T_MYSQL_H_
#define MAX_NAME_LENGTH 128
#define MAX_QUERY_LENGTH 1024
typedef struct {
MYSQL *con;
char password[MAX_NAME_LENGTH];
char root_password[MAX_NAME_LENGTH];
char user[MAX_NAME_LENGTH];
char server[MAX_NAME_LENGTH];
char database_name[MAX_NAME_LENGTH];
char table_name[MAX_NAME_LENGTH];
char query_create_table[MAX_QUERY_LENGTH];
char query_create_db[MAX_QUERY_LENGTH];
char query_data[MAX_QUERY_LENGTH];
}T_MYSQL;
void finish_with_error(MYSQL *con);
int t_mysql_init(T_MYSQL *mysql);
int t_mysql_connect(T_MYSQL *mysql);
int t_mysql_disconnect(T_MYSQL *mysql);
int t_mysql_createdb(T_MYSQL *mysql);
int t_mysql_createtable(T_MYSQL *mysql);
int t_mysql_setdb(T_MYSQL *mysql);
int t_mysql_insertdata(T_MYSQL *mysql);
int t_mysql_quickinsert(T_MYSQL *mysql);
#endif /* T_MYSQL_H_ */
t-mysql.c:
#include <stdio.h>
#include <mysql.h>
#include <my_global.h>
#include "t-mysql.h"
void finish_with_error(MYSQL *con){
fprintf(stderr, "%s\n", mysql_error(con));
mysql_close(con); //close connection to database
}
int t_mysql_init(T_MYSQL *mysql){
mysql->con = mysql_init(NULL);
if (mysql->con == NULL){
finish_with_error(mysql->con);
return 0;
}
return 1;
}
int t_mysql_connect(T_MYSQL *mysql){
// connect to MySQL
if (mysql_real_connect(mysql->con, mysql->server, mysql->user, mysql->password,NULL, 0, NULL, 0) == NULL){
finish_with_error(mysql->con);
return 0;
}
return 1;
}
int t_mysql_disconnect(T_MYSQL *mysql){
mysql_close(mysql->con);
if ( mysql->con == NULL){
finish_with_error(mysql->con);
return 0;
}
return 1;
}
int t_mysql_createdb(T_MYSQL *mysql){
t_mysql_disconnect(mysql); //disconnect normal user
//connect as root
t_mysql_init(mysql);
if (mysql_real_connect(mysql->con, mysql->server, "root", mysql->root_password,NULL, 0, NULL, 0) == NULL){
finish_with_error(mysql->con);
return 0;
}
// create DB, if it doesn't exist
if (mysql_select_db(mysql->con, mysql->database_name)){
if (mysql_query(mysql->con, mysql->query_create_db)){
finish_with_error(mysql->con);
return 0;
}
else {
fprintf(stdout,"Database %s created\n",mysql->database_name);
}
}else{
fprintf(stdout,"Database %s exists\n",mysql->database_name);
}
//disconnect root user
t_mysql_disconnect(mysql);
//connect as normal user
t_mysql_init(mysql);
t_mysql_connect(mysql);
return 1;
}
int t_mysql_setdb(T_MYSQL *mysql){
if (mysql_select_db(mysql->con, mysql->database_name) == NULL){
finish_with_error(mysql->con);
return 0;
}
return 1;
}
int t_mysql_createtable(T_MYSQL *mysql){
//create table:
if(mysql_query(mysql->con, mysql->query_create_table)){
finish_with_error(mysql->con);
return 0;
}
return 1;
}
int t_mysql_insertdata(T_MYSQL *mysql){
if (mysql_query(mysql->con, mysql->query_data)) {
finish_with_error(mysql->con);
return 0;
}
return 1;
}
I didn't test your code on my system, but I think, the error is here:
int t_mysql_setdb(T_MYSQL *mysql){
if (mysql_select_db(mysql->con, mysql->database_name) == NULL){//<-?
finish_with_error(mysql->con);
return 0;
}
return 1;
}
You are thinking, that 0 is the returned, when there is an error, while connecting. While MySQL docs say, that the opposite is true:
int mysql_select_db(MYSQL *mysql, const char *db)
Return Values:
Zero for success. Nonzero if an error occurred.
http://dev.mysql.com/doc/refman/5.5/en/mysql-select-db.html
So, you are checking for a wrong value. It means, that this statement:
I called mysql_select_db() and it returned no errors
Is false, and there is an error in this function, that you don't catch.
I wrote a program in c language with mysql.
It does not work well.
I create a connect function to help me connect mysql
MYSQL *ts_mysql_connect(char *host, char *user, char *pass, char *database)
{
MYSQL *conn = mysql_init(NULL);
fprintf(stderr, "[ts_mysql_connect] conn-> %ld\n", conn);
if (!mysql_real_connect(conn, host, user, pass, database, 0, NULL, 0)){
fprintf(stderr, "%s\n", mysql_error(conn));
exit(1);
}
//set auto commit to false
if (mysql_autocommit(conn, 0))
fprintf(stderr, "%s\n", "SET MYSQL autocommit to off faild!");
fprintf(stderr, "[ts_mysql_connect] conn-> %ld\n", conn);
return conn;
}
and I use below the code below to call my function
MYSQL *test;
test = ts_mysql_connect(conf->run_conf->mysql_host,
conf->run_conf->mysql_user,
conf->run_conf->mysql_pass,
conf->run_conf->mysql_database);
conf->mysql_start = time(NULL);
if (verbose)
fprintf(stderr, "[ts_mysql_insert] mysql conn init at %ld\n",
&test);
exit(1);
i donot know why ts_mysql_connect return different address of the conn.
run log:
[ts_mysql_connect] conn-> 140065527302336
[ts_mysql_connect] conn-> 140065527302336
[ts_mysql_insert] mysql conn init at -1946154816
So why MYSQL *conn in [ts_mysql_insert] and [ts_mysql_connect] have different address
You didn't declare the function prototype of ts_mysql_connect in the second program, so the compiler assumes that the function returns an int type.
If you use -Wall directive to enable all warnings, you will see a warning message like this:
warning: implicit declaration of function ‘ts_mysql_connect’
#include <stdio.h>
#include <stdlib.h>
#include <my_global.h>
#include <mysql.h>
MYSQL *DatabaseConnection;
const char *ServerName = "192.168.1.12";
const char *User = "dbuser";
const char *Password = "dbpassword";
const char *Name = "test";
const char *DB_Socket_Path = "/var/run/mysqld/mysql.sock";
int execute_db_query(const char *sql_query)
{
MYSQL_RES *result = NULL;
MYSQL_ROW row;
int num_fields;
int i;
if (!DatabaseConnection)
return -1;
mysql_query(DatabaseConnection, sql_query);
result = mysql_store_result(DatabaseConnection);
if(result == NULL)
{
mysql_free_result(result);
return -1;
}
if (!result->eof) {
mysql_free_result(result);
return -1;
}
num_fields = mysql_num_fields(result);
int f_count = result->field_count;
int index =1 ;
while ((row = mysql_fetch_row(result))) {
for (i = 0; i < num_fields; i++) {
printf("%s ", row[i] ? row[i] : "NULL");
}
printf("\n");
index++;
}
mysql_free_result(result);
return 0;
}
void close_db_connection() {
mysql_close(DatabaseConnection);
mysql_library_end();
}
int init_connect() {
DatabaseConnection = mysql_init(NULL);
printf("MySQL client version: %s\n", mysql_get_client_info());
if (!mysql_real_connect(DatabaseConnection, ServerName, User, Password,
Name, 0, DB_Socket_Path, 0)) {
puts(mysql_error(DatabaseConnection));
close_db_connection();
return -1;
}
printf("Host : %s \n", mysql_get_host_info(DatabaseConnection));
printf("Server : %s: \n", mysql_get_server_info(DatabaseConnection));
printf("Protocol : %d\n", mysql_get_proto_info(DatabaseConnection));
return 0;
}
int main(void) {
puts("SQL Example");
init_connect() ;
execute_db_query("select * from test");
return EXIT_SUCCESS;
}
I see you are using socket less connection so you can pass NULL in this case.
I get too many connections when I try to connect to MySQL.
Why did I get that error although I close the connection whenever I connect to the MySQL server?
How should I solve that problem?
UPDATE
I run this on Ubuntu. My project is CGI which is written with C.
My web server is Apache.
This is an example of my source Code. Others are almost the same.
#include <mysql.h>
#include <stdio.h>
#include <string.h>
MYSQL *conn;
MYSQL_RES *res;
MYSQL_ROW row;
char *server = "localhost";
char *user = "root";
char *password = "jitcomm"; /* set me first */
char *database = "profile";
int main(int argc, char *argv[])
{
if(argc==1)
getAll();
else
getOneUser(argv[1]);
return 0;
}
// show user
void getAll()
{
char query[500];
char result[1024];
memset(result,0,1024);
memset(query,0,500);
conn = mysql_init(NULL);
int i;
FILE *fout;
if((fout = fopen("gUsers","w"))==NULL)
{
printf("error with file");
}
/* Connect to database */
if (!mysql_real_connect(conn, server,
user, password, database, 0, NULL, 0)) {
fprintf(stderr, "%s\n", mysql_error(conn));
exit(1);
}
/* send SQL query */
sprintf(query,"select * from userTbl");
if (mysql_query(conn, query))
{
fprintf(stderr, "%s\n", mysql_error(conn));
exit(2);
}
res = mysql_use_result(conn);
/* output table name */
system("clear");
sprintf(result,"ID\t Name\t Password\t Role\n");
while ((row = mysql_fetch_row(res)) != NULL)
{
//printf("%s \n", row[0]);
//strcpy(id,row[0]);
sprintf(query,"%s\t %s\t %s\t\t %s\n",row[0], row[1], row[2], row[3]);
strcat(result,query);
for(i = 1 ;i<4;i++)
{
if(i==1)
fprintf(fout,"%s\n",row[i]); //write data to the file
if(i==2)
fprintf(fout,"%s\n",row[i]); //write data to the file
if(i==3)
fprintf(fout,"%s\n",row[i]); //write data to the file
}
}
/* close connection */
mysql_free_result(res);
mysql_close(conn);
//printf(result);
}
void getOneUser(char *n)
{
char query[500];
char result[1024];
memset(result,0,1024);
memset(query,0,500);
conn = mysql_init(NULL);
int i;
FILE *fout;
if((fout = fopen("gUsers","w"))==NULL)
{
printf("error with file");
}
/* Connect to database */
if (!mysql_real_connect(conn, server,
user, password, database, 0, NULL, 0)) {
fprintf(stderr, "%s\n", mysql_error(conn));
exit(1);
}
/* send SQL query */
sprintf(query,"select * from userTbl where name = '%s'",n);
if (mysql_query(conn, query))
{
fprintf(stderr, "%s\n", mysql_error(conn));
exit(2);
}
res = mysql_use_result(conn);
/* output table name */
system("clear");
sprintf(result,"ID\t Name\t Password\t Role\n");
while ((row = mysql_fetch_row(res)) != NULL)
{
//printf("%s \n", row[0]);
// //strcpy(id,row[0]);
sprintf(query,"%s\t %s\t %s\t\t %s\n",row[0], row[1], row[2], row[3]);
strcat(result,query);
for(i = 1 ;i<4;i++)
{
if(i==1)
fprintf(fout,"%s\n",row[i]); //write data to the file
if(i==2)
fprintf(fout,"%s\n",row[i]); //write data to the file
if(i==3)
fprintf(fout,"%s\n",row[i]); //write data to the file
}
}
/* close connection */
mysql_free_result(res);
mysql_close(conn);
//printf(result);
}