Unix Programming - strange problem with MySQL

This is Interesting: Free IT Magazines  
Home > Archive > Unix Programming > November 2005 > strange problem with MySQL





You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

Author strange problem with MySQL
Roman Mashak

2005-11-26, 2:50 am

Hello, All!

I use mysql 5.1 (client and server are og same version), Linux 2.4.20
kernel.
#define MSGLEN 32
#define BUFFLEN 1024

int db_init(MYSQL *Conn)
{
MYSQL *c;

c = malloc(sizeof(MYSQL));
if ( c == NULL )
return 0;

memcpy(c, Conn, sizeof(MYSQL));
/* initialize the connection object here */
if ( mysql_init(Conn) == NULL ) {
free(c);
return FAIL;
}

/* connect main database here */
if( !mysql_real_connect(Conn, c->host, c->user, c->passwd, c->db, 0,
NULL, 0) ) {
free(c);
return FAIL;
}

/* select database */
if( mysql_select_db(Conn, c->db) ) {
free(c);
return FAIL;
}


free(c);
return SUCCESS;
}

typedef struct msg_s {
unsigned char msg_flag;
unsigned char msg_type;
unsigned char msg_rc; /* reply code */
char msg_id[MSGLEN];
char msg_passwd[MSGLEN];
char msg_fqdn[MSGLEN];
char msg_ipaddr[MSGLEN];
char msg_serialno[MSGLEN];
} msg_t;

msg_t *msg, *msg2;
MYSQL conn;
....
msg = malloc( sizeof(msg_t) );
msg2 = malloc( sizeof(msg_t) );
if ( !msg || !msg2 ) {
/* error message */
exit(EXIT_FAILURE);
}



/* here I call function getting data ina form of structure 'msg_t' from
network. Data are not corrupted, checked */

/* keep copy of buffer */
memcpy(msg2, msg, sizeof(msg_t));

/* prepare to initialize mysql */
conn.host = "192.168.11.22";
conn.user = "user";
conn.passwd = "pass";
conn.db = "userdb";

if ( db_init(&conn) != SUCCESS ) {
/* error message */
...
}

Right after this function 'msg' and 'msg2' point to 0x00, no matter was
db_init() succesfull ot not. Naturally, further handling of these pointers
results in segmentation fault.

If important, compilation flags are:
#gcc -W -Wall -g -I/usr/local/mysql/lib/mysql -L/usr/local/mysql/lib/mysql
.... -lmysqlclient

Where can be the problem?

With best regards, Roman Mashak. E-mail: mrv@tusur.ru


Bjørn Augestad

2005-11-26, 2:50 am

Roman Mashak wrote:
> Hello, All!
>
> I use mysql 5.1 (client and server are og same version), Linux 2.4.20
> kernel.
> #define MSGLEN 32
> #define BUFFLEN 1024
>
> int db_init(MYSQL *Conn)
> {
> mysql *c;

(Disclaimer: I am not familiar with MySQL)
1. Why do you create the variable c? Can't you just use Conn instead?
2. Why do you allocate c on the heap instead of the stack? Saves you
a lot of of calls to free().

>
> c = malloc(sizeof(MYSQL));
> if ( c == NULL )
> return 0;


if( (c = malloc(sizeof *c)) == NULL)
return NULL;
>
> memcpy(c, Conn, sizeof(MYSQL));

*c = *Conn; works too.

[snip]

> If important, compilation flags are:
> #gcc -W -Wall -g -I/usr/local/mysql/lib/mysql -L/usr/local/mysql/lib/mysql
> .... -lmysqlclient
>
> Where can be the problem?


Hard to tell. Have you tried to run valgrind(http://valgrind.kde.org) on
your executable? If not, do that first. Valgrind will find the error,
guaranteed. It is so good it takes all the fun out of debugging ;-)

Bjørn

Roman Mashak

2005-11-26, 5:50 pm

Hello, Bjørn!
You wrote on Sat, 26 Nov 2005 07:01:30 +0100:

??>> {
??>> mysql *c;
BA> (Disclaimer: I am not familiar with MySQL)
BA> 1. Why do you create the variable c? Can't you just use Conn instead?
BA> 2. Why do you allocate c on the heap instead of the stack? Saves you
BA> a lot of of calls to free().
What do you mean here? Could you please clarify?

BA> Hard to tell. Have you tried to run valgrind(http://valgrind.kde.org)
BA> on your executable? If not, do that first. Valgrind will find the
BA> error, guaranteed. It is so good it takes all the fun out of debugging
BA> ;-)
Is is a sort of 'slint' ?

With best regards, Roman Mashak. E-mail: mrv@tusur.ru


Bjørn Augestad

2005-11-26, 5:50 pm

Roman Mashak wrote:
> Hello, Bjørn!
> You wrote on Sat, 26 Nov 2005 07:01:30 +0100:
>
> ??>> {
> ??>> mysql *c;
> BA> (Disclaimer: I am not familiar with MySQL)
> BA> 1. Why do you create the variable c? Can't you just use Conn instead?
> BA> 2. Why do you allocate c on the heap instead of the stack? Saves you
> BA> a lot of of calls to free().
> What do you mean here? Could you please clarify?

Sure. It looked to me as the variable named c wasn't needed. IIRC all
the code did was to create c and copy conn to c. Then the code used some
members (username/password) from c to connect to the database. Unless
the mysql functions modify its arguments, c can be replaced with conn.

>
> BA> Hard to tell. Have you tried to run valgrind(http://valgrind.kde.org)
> BA> on your executable? If not, do that first. Valgrind will find the
> BA> error, guaranteed. It is so good it takes all the fun out of debugging
> BA> ;-)
> Is is a sort of 'slint' ?

Sort of, but not really. Splint analyzes source code and valgrind
analyzes program behaviour at runtime.

To quote its web site:
"Valgrind is an award-winning suite of tools for debugging and profiling
Linux programs. With the tools that come with Valgrind, you can
automatically detect many memory management and threading bugs, avoiding
hours of frustrating bug-hunting, making your programs more stable. You
can also perform detailed profiling, to speed up and reduce memory use
of your programs."

IMO no one should code C/C++ on Linux without using valgrind.

Bjørn
Gordon Burditt

2005-11-26, 8:48 pm

>I use mysql 5.1 (client and server are og same version), Linux 2.4.20
>kernel.


The mysql type is supposed to be an opaque type and you're not
supposed to tinker with the insides of it. Assuming that it's GOT
elements user, host, passwd, and db is not a good idea, and assuming
that they are of type "char *" is worse.

However, it seems that you tinker with these only before calling
mysql_init() or only on a copy, this shouldn't cause trouble.
Contrary to suggestions in other replies, making a copy of Conn
*is* necessary, as mysql_init() initializes it, wiping out
the pointers to stuff set in the code that calls db_init().

I can only assume that your problem is caused by code you don't
show, possibly involving abuse of malloc/free. Why DO you allocate
two message buffers and then copy one uninitialized message buffer
into the other one?

One possible problem is using a <mysql/mysql.h> header that doesn't
match the library you are linking with, especially if they disagree
about the size of the mysql type.

Gordon L. Burditt

>#define MSGLEN 32
>#define BUFFLEN 1024
>
>int db_init(MYSQL *Conn)
>{
> mysql *c;
>
> c = malloc(sizeof(MYSQL));
> if ( c == NULL )
> return 0;
>
> memcpy(c, Conn, sizeof(MYSQL));
> /* initialize the connection object here */
> if ( mysql_init(Conn) == NULL ) {
> free(c);
> return FAIL;
> }
>
> /* connect main database here */
> if( !mysql_real_connect(Conn, c->host, c->user, c->passwd, c->db, 0,
>NULL, 0) ) {
> free(c);
> return FAIL;
> }
>
> /* select database */
> if( mysql_select_db(Conn, c->db) ) {
> free(c);
> return FAIL;
> }
>
>
> free(c);
> return SUCCESS;
>}
>
>typedef struct msg_s {
>unsigned char msg_flag;
> unsigned char msg_type;
> unsigned char msg_rc; /* reply code */
> char msg_id[MSGLEN];
> char msg_passwd[MSGLEN];
> char msg_fqdn[MSGLEN];
> char msg_ipaddr[MSGLEN];
>char msg_serialno[MSGLEN];
>} msg_t;
>
>msg_t *msg, *msg2;
>MYSQL conn;
>...
>msg = malloc( sizeof(msg_t) );
>msg2 = malloc( sizeof(msg_t) );
>if ( !msg || !msg2 ) {
> /* error message */
> exit(EXIT_FAILURE);
>}
>
>
>
>/* here I call function getting data ina form of structure 'msg_t' from
>network. Data are not corrupted, checked */
>
>/* keep copy of buffer */
>memcpy(msg2, msg, sizeof(msg_t));
>
>/* prepare to initialize mysql */
>conn.host = "192.168.11.22";
>conn.user = "user";
>conn.passwd = "pass";
>conn.db = "userdb";
>
>if ( db_init(&conn) != SUCCESS ) {
> /* error message */
> ...
>}
>
>Right after this function 'msg' and 'msg2' point to 0x00, no matter was
>db_init() succesfull ot not. Naturally, further handling of these pointers
>results in segmentation fault.
>
>If important, compilation flags are:
>#gcc -W -Wall -g -I/usr/local/mysql/lib/mysql -L/usr/local/mysql/lib/mysql
>... -lmysqlclient
>
>Where can be the problem?
>
>With best regards, Roman Mashak. E-mail: mrv@tusur.ru
>
>



Roman Mashak

2005-11-27, 2:50 am

Hello, Gordon!
You wrote on Sun, 27 Nov 2005 01:51:34 -0000:

GB> The mysql type is supposed to be an opaque type and you're not
GB> supposed to tinker with the insides of it. Assuming that it's GOT
GB> elements user, host, passwd, and db is not a good idea, and assuming
GB> that they are of type "char *" is worse.
Actually all I'm doing with the object of this type is passing necessary
arguments via it, because in any case I need 'MYSQL *Conn' from the caller
of db_init() - so, why not to pass id/password/db arguments in a an shot?
GB> However, it seems that you tinker with these only before calling
GB> mysql_init() or only on a copy, this shouldn't cause trouble.
GB> Contrary to suggestions in other replies, making a copy of Conn
GB> *is* necessary, as mysql_init() initializes it, wiping out
GB> the pointers to stuff set in the code that calls db_init().
Absolutely true, I found only one way to avoid this - duplicate pointer.
GB> I can only assume that your problem is caused by code you don't
GB> show, possibly involving abuse of malloc/free. Why DO you allocate
GB> two message buffers and then copy one uninitialized message buffer
GB> into the other one?
This is because of program's logic (might be it should be changed), I
receive data from network in this buffer and then using *same* pointer, send
back response, so I need to save them before.
GB> One possible problem is using a <mysql/mysql.h> header that doesn't
GB> match the library you are linking with, especially if they disagree
GB> about the size of the mysql type.
You're right, that was exactly the problem, I missed the correct include
directory.

With best regards, Roman Mashak. E-mail: mrv@tusur.ru


Gordon Burditt

2005-11-27, 5:53 pm

> GB> The mysql type is supposed to be an opaque type and you're not
> GB> supposed to tinker with the insides of it. Assuming that it's GOT
> GB> elements user, host, passwd, and db is not a good idea, and assuming
> GB> that they are of type "char *" is worse.
>Actually all I'm doing with the object of this type is passing necessary
>arguments via it, because in any case I need 'MYSQL *Conn' from the caller
>of db_init() - so, why not to pass id/password/db arguments in a an shot?


Because if the mysql type ceases to have members named user, db,
passwd, etc. (perhaps in a later release) your program will fail
to compile. It could also cease to be a struct, or the members
could change type from, say, char * to a char array. Having such
members or their type is not a documenteed feature of MySQL, and
you shouldn't depend on it for your program to work.

You are free to define your own structure to pass the connection
parameters in, and pass THAT along with Conn.

> GB> However, it seems that you tinker with these only before calling
> GB> mysql_init() or only on a copy, this shouldn't cause trouble.
> GB> Contrary to suggestions in other replies, making a copy of Conn
> GB> *is* necessary, as mysql_init() initializes it, wiping out
> GB> the pointers to stuff set in the code that calls db_init().
>Absolutely true, I found only one way to avoid this - duplicate pointer.


The way to avoid it is not to duplicate the pointer but to duplicate
the structure (which you did).

> GB> I can only assume that your problem is caused by code you don't
> GB> show, possibly involving abuse of malloc/free. Why DO you allocate
> GB> two message buffers and then copy one uninitialized message buffer
> GB> into the other one?
>This is because of program's logic (might be it should be changed), I
>receive data from network in this buffer and then using *same* pointer, send
>back response, so I need to save them before.


But you're saving *UNINITIALIZED DATA*. Or perhaps you left out
the part where you initialized the buffers.

> GB> One possible problem is using a <mysql/mysql.h> header that doesn't
> GB> match the library you are linking with, especially if they disagree
> GB> about the size of the mysql type.
>You're right, that was exactly the problem, I missed the correct include
>directory.

Sponsored Links






Free braindumps | Software forum | Database administration forum

Copyright 2003 - 2008 webservertalk.com