13 Feb, 2011, Miker wrote in the 1st comment:
Votes: 0
I've been having a problem with mysql_fetch_row() crashing my Socketmud. I've made sure that the result is not null and that the number of rows in the result is greater than zero. Anything else I should check for that would make mysql_fetch_row() cause a crash?
13 Feb, 2011, David Haley wrote in the 2nd comment:
Votes: 0
Do you have more information, e.g. a backtrace or what lines of code are causing trouble?
14 Feb, 2011, Miker wrote in the 3rd comment:
Votes: 0
The function:
SOCK_LIST * nation_list()
{
SOCK_LIST *nlist;
char buf[MAX_BUFFER];

nlist = AllocList();

sprintf(buf,"SELECT * FROM nations");
db_query("SELECT * FROM nations");
result = mysql_store_result(&mysqlconn);
if(result == NULL) return nlist;
if(mysql_num_rows(result) < 1) return nlist;
while ((row = mysql_fetch_row (result)) != NULL) /* This line is where the problem is */
{
NATION_DATA *n = nation_create();
nation_load(n,atoi( row[0] ));
AttachToList(n,nlist);
n = NULL;
}
db_free();
return nlist;
}


The backtrace is:
#0  0x00b66ddd in mysql_fetch_row () from /usr/lib/mysql/libmysqlclient.so.15
#1 0x0804f153 in nation_list () at nation.c:75
#2 0x0804f182 in cmd_nation_list (ch=0x83892e0, argument=0x8395323 "") at nation.c:92
#3 0x0804c804 in handle_cmd_input (dsock=0x8391310, arg=0x8395323 "") at interp.c:29
#4 0x08051089 in GameLoop (control=3) at socket.c:181
#5 0x08050e0c in main (argc=1, argv=0xbfac3e64) at socket.c:87
14 Feb, 2011, Zeno wrote in the 4th comment:
Votes: 0
Where is result coming from? I don't see it declared.
14 Feb, 2011, David Haley wrote in the 5th comment:
Votes: 0
What about the connection; are you sure it's valid? What is db_query doing – is it leaving the connection in a valid state?
14 Feb, 2011, Exodus wrote in the 6th comment:
Votes: 0
Zeno said:
Where is result coming from? I don't see it declared.

Zeno has a point there. Make sure you have pointers to those structs declared either somewhere locally in the function or within the scope of the file.
Also, where is the declaration for row?
Try adding something like this to the the function:
MYSQL_ROW row;
MYSQL_RES *result;
14 Feb, 2011, David Haley wrote in the 7th comment:
Votes: 0
You don't see the declaration but you see the assignment, and that's all that really matters here. (If it weren't declared, it wouldn't compile. The assignment voids whatever good or bad value it had previously.) What's more worrisome is when you don't see how globals like the connection are managed.
14 Feb, 2011, Miker wrote in the 8th comment:
Votes: 0
All db_query does is mysql_real_query(). If mysql_real_query() returns an error, it logs the error with mysql_error(). I use db_query in many places throughout the code, and it works fine. It just crashes in this particular function.
14 Feb, 2011, Davion wrote in the 9th comment:
Votes: 0
I don't see a check to see if the resault set is empty. Try putting a check tomake sure mysql_numrows returns > 0
14 Feb, 2011, David Haley wrote in the 10th comment:
Votes: 0
Does it die on the first row fetch, or somewhere after the first?
14 Feb, 2011, Miker wrote in the 11th comment:
Votes: 0
I didn't think to look for that. It does the first one, but then dies. There are four other rows in the DB.
14 Feb, 2011, David Haley wrote in the 12th comment:
Votes: 0
What about this from the manual:

Quote
mysql_store_result() also returns a null pointer if reading of the result set failed. You can check whether an error occurred by checking whether mysql_error() returns a nonempty string, mysql_errno() returns nonzero, or mysql_field_count() returns zero.

You don't seem to be checking for those, although you are checking for the null.


Is this the first DB read in your entire program? What if you set it to be the first? Perhaps you are not cleaning up the DB correctly in some prior read.

Are the values read in for the first row useful, or garbage?
14 Feb, 2011, Miker wrote in the 13th comment:
Votes: 0
Well, I'll be damned. It something entirely stupid on my part as I expected. You see the call to nation_load() in the while loop? That function uses the same global result pointer and then clears it when it's done. I really should use a local result set in the function rather than have one declared globally. How I've missed these dumb oversights since I've starting coding again.

Thanks for the help. May the Source be with Y'all.
14 Feb, 2011, David Haley wrote in the 14th comment:
Votes: 0
This is a pretty classic example of why globals are bad. :smile: Glad you found the problem! These things usually have to do with connections being left in invalid states one way or another.
0.0/14