mysql c api 多结果集时,上下文分配空间,内存访问越界
最近想做一个访问mysql的c程序, 使用mysqlclient 来访问mysql。在做单个结果集时, 没有发生问题。访问多结果集时,出现莫名其妙的崩溃。请路过的朋友帮忙分析一下。
我把代码全部贴出来吧:
#include<mysql.h>
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
struct col_def{
char* col_name; // col_name unalloc
int col_name_len;
int field_type; // ??
};
struct col_def* create_col_def( ){
struct col_def* ptr = NULL;
ptr = (struct col_def *)malloc(sizeof(struct col_def));
ptr->col_name = NULL;
ptr->col_name_len = 0;
ptr->field_type = 0;
return ptr;
}
void destroy_col_def( struct col_def* def ){
free( def->col_name );
free( def );
}
struct field_data{
int data_len; // data len
char* data; // data unalloc
};
struct field_data* create_field_data( ){
struct field_data* ptr = NULL;
ptr = (struct field_data *)malloc(sizeof(struct field_data));
ptr->data = NULL;
ptr->data_len = 0;
return ptr;
}
void destroy_field_data( struct field_data* data ){
free( data->data );
free( data );
}
struct res_info{
int error_code;
int affect_rows;
int row_num;
int col_num;
struct col_def* col_defs; // alloc
int file_data_count;
struct field_data* file_data; // alloc
};
struct res_info* create_res_info( ){
struct res_info* ptr = NULL;
ptr = (struct res_info *)malloc(sizeof(struct res_info));
ptr->error_code = 0;
ptr->affect_rows = 0;
ptr->row_num = 0;
ptr->col_num = 0;
ptr->file_data_count = 0;
return ptr;
}
void destroy_res_info( struct res_info* res_info ){
inti = 0;
for( i = 0; i < res_info->col_num; i++ )
destroy_col_def( res_info->col_defs );
for( i = 0; i < res_info->file_data_count; i++ )
destroy_field_data( res_info->file_data );
free( res_info );
}
intres_info_total_len( struct res_info* res_info ){
int len = 0;
len += 4;
len += 4;
len += 4;
int i = 0;
len += 4;
for( i = 0; i < res_info->col_num; i++ ){
struct col_def* def = res_info->col_defs[ i ];
len += 4; //type
len += 4; // len
len += def->col_name_len; // data
}
len += 4;
for( i = 0; i < res_info->file_data_count; i++ ){
struct field_data* def = res_info->file_data[ i ];
len += 4; // len
len += def->data_len; // data
}
return len;
}
void debug_res_info( struct res_info* res_info ){
printf("debug res_info........\r\n");
printf("res_info->error_code=%d\r\n", res_info->error_code );
printf("res_info->affect_rows=%d\r\n", res_info->affect_rows );
printf("res_info->row_num=%d\r\n", res_info->row_num );
printf("res_info->col_num=%d\r\n", res_info->col_num );
printf("res_info->file_data_count=%d\r\n", res_info->file_data_count );
printf("res_info col_defs\r\n" );
int i = 0;
for( i = 0; i < res_info->col_num; i++ ){
struct col_def* def = res_info->col_defs[ i ];
printf(" def name=%s, type=%d\r\n", def->col_name, def->field_type );
}
printf("res_info file_data\r\n" );
for( i = 0; i < res_info->file_data_count; i++ ){
struct field_data* def = res_info->file_data[ i ];
printf(" data name=%s, type=%d\r\n", def->data, def->data_len );
}
}
void res_info_alloc_col_def( struct res_info* res_info){
if( res_info->col_num == 0 )
return;
//res_info->col_defs = (struct col_def*)malloc( sizeof(struct col_def*)*res_info->col_num);
}
void res_info_set_col_def( struct res_info* res_info, int index, struct col_def* def ){
if( index >= res_info->col_num )
return;
res_info->col_defs = def;
}
void res_info_alloc_field_data( struct res_info* res_info){
if( res_info->file_data_count == 0 )
return;
//res_info->file_data = (struct field_data*)malloc( sizeof(struct field_data)*res_info->file_data_count);
}
void res_info_set_field_data( struct res_info* res_info, int index, struct field_data* data ){
if( index >= res_info->file_data_count )
return;
res_info->file_data = data;
}
void pack_res_info( struct res_info* res_info, char* buffer ){
printf("pack_res_info\r\n" );
int offset = 0;
int test_int = 0;
memcpy( buffer + offset, &res_info->error_code, 4);
memcpy( &test_int, buffer + offset, 4 );
offset += 4;
memcpy( buffer + offset, &res_info->affect_rows, 4);
memcpy( &test_int, buffer + offset, 4 );
offset += 4;
memcpy( buffer + offset, &res_info->row_num, 4);
memcpy( &test_int, buffer + offset, 4 );
offset += 4;
memcpy( buffer + offset, &res_info->col_num, 4); offset += 4;
int i = 0;
for( i = 0; i < res_info->col_num; i++ ){
struct col_def* def = res_info->col_defs[ i ];
memcpy( buffer + offset, &def->field_type, 4); offset += 4;
memcpy( buffer + offset, &def->col_name_len, 4); offset += 4;
memcpy( buffer + offset, def->col_name, def->col_name_len);
printf("pack_res_infodef->col_name=%s \r\n", buffer + offset );
offset += def->col_name_len;
}
memcpy( buffer + offset, &res_info->file_data_count, 4); offset += 4;
for( i = 0; i < res_info->file_data_count; i++ ){
struct field_data* def = res_info->file_data[ i ];
memcpy( buffer + offset, &def->data_len, 4); offset += 4;
memcpy( buffer + offset, def->data, def->data_len);
printf("pack_res_infodef->data=%s \r\n", buffer + offset );
offset += def->data_len;
}
printf("pack_res_infowrite buff = %d \r\n", offset );
}
void debug_bytes( char* buffer, int len ){
}
struct res_info* unpack_res_info( char* buffer, int len ){
debug_bytes( buffer, 96 );
printf("unpack_res_info buffer=%s\r\n", buffer+28 );
struct res_info* res_info = create_res_info( );
int offset = 0;
memcpy( &res_info->error_code, buffer + offset, 4 ); offset += 4;
memcpy( &res_info->affect_rows,buffer + offset, 4 ); offset += 4;
memcpy( &res_info->row_num, buffer + offset, 4 ); offset += 4;
int i = 0;
memcpy( &res_info->col_num, buffer + offset, 4 ); offset += 4;
for( i = 0; i < res_info->col_num; i++ ){
struct col_def* def = create_col_def( );
memcpy( &def->field_type, buffer + offset, 4); offset += 4;
memcpy( &def->col_name_len, buffer + offset, 4); offset += 4;
def->col_name = (char*)malloc( def->col_name_len + 1 );
memset( def->col_name, 0,def->col_name_len + 1 );
memcpy( def->col_name, buffer + offset, def->col_name_len); offset += def->col_name_len;
res_info_set_col_def( res_info, i, def );
}
//int count = 0;
memcpy( &res_info->file_data_count, buffer + offset, 4 ); offset += 4;
for( i = 0; i < res_info->file_data_count; i++ ){
struct field_data* def = create_field_data( );
memcpy( &def->data_len, buffer + offset, 4); offset += 4;
def->data = (char*)malloc( def->data_len + 1 );
memset( def->data, 0,def->data_len + 1 );
memcpy( def->data, buffer + offset, def->data_len); offset += def->data_len;
res_info_set_field_data( res_info, i, def);
}
//res_info->file_data_count = count;
printf("unpack_res_inforead buff = %d \r\n", offset );
return res_info;
}
struct sql_results {
struct res_info* res_infos; //
int res_num;
int error_flag;
};
struct sql_results* sql_results_create( ) {
printf(" sizeof( struct sql_results )=%ld\r\n", sizeof( struct sql_results ) );
struct sql_results* ptr = (struct sql_results*)malloc( sizeof( struct sql_results ) );
printf(" sql_results_create 0\r\n" );
ptr->res_num = 0;
ptr->error_flag = 0;
return ptr;
}
void sql_results_destroy( struct sql_results* reslut ) {
int i = 0;
for( i = 0; i < reslut->res_num; i++ )
destroy_res_info( reslut->res_infos);
free( reslut );
}
void sql_results_set_res_info( struct sql_results* results, int index, struct res_info* res_info ){
printf(" sql_results_set_res_info index=%d\r\n", index );
if( index >= 10 ){
printf(" over flow sql_resultscur maxnum=%d\r\n", 5 );
return;
}
results->res_infos[ index ] = res_info;
}
int sql_results_set_total_len( struct sql_results* results ){
int i = 0;
int len = 0;
len += 4;
len += 4;
for( i = 0; i < results->res_num; i++ )
len += res_info_total_len( results->res_infos[ i ]);
return len;
}
void sql_results_set_total_debug( struct sql_results* results ){
printf(" results->error_flag=%d\r\n", results->error_flag );
printf(" results->res_num=%d\r\n", results->res_num );
int i = 0;
for( i = 0; i < results->res_num; i++ )
debug_res_info( results->res_infos );
}
void pack_sql_results_set( struct sql_results* results, char* buffer ) {
int offset = 0;
memcpy( buffer + offset, &results->error_flag, 4); offset += 4;
memcpy( buffer + offset, &results->res_num, 4);
int num = 0;
memcpy( &num, buffer + offset, 4 );
offset += 4;
int i = 0;
for( i = 0; i < results->res_num; i++ ){
struct res_info* res_info = results->res_infos[ i ];
pack_res_info( res_info, (char*)(buffer + offset) );
int test_int = 0;
memcpy( &test_int, buffer + 0 + 8, 4 );
printf(" pack_sql_results_set test_int1=%d\n", test_int );
memcpy( &test_int, buffer + 4 + 8, 4 );
printf(" pack_sql_results_set test_int2=%d\n", test_int );
memcpy( &test_int, buffer + 8 + 8, 4 );
printf(" pack_sql_results_set test_int3=%d\n", test_int );
memcpy( &test_int, buffer + 12 + 8, 4 );
printf(" pack_sql_results_set test_int4=%d\n", test_int );
malloc( 20 );
memcpy( &test_int, buffer + 16 + 8, 4 );
printf(" pack_sql_results_set test_int5=%d\n", test_int );
malloc( 20 );
// struct res_info* res_info_temp = unpack_res_info( (char*)(buffer + offset), res_info_total_len( res_info ) );
// debug_res_info( res_info_temp );
offset += res_info_total_len( res_info );
printf(" pack_sql_results_set unpack_sql_results_set i = %d\r\n", i );
}
}
struct sql_results* unpack_sql_results_set( char* buffer, int len ) {
printf("begin unpack_sql_results_set\r\n" );
int offset = 0;
printf(" unpack_sql_results_set0\r\n" );
struct sql_results* results = sql_results_create( );
memcpy( &results->error_flag, buffer + offset, 4 ); offset += 4;
memcpy( &results->res_num, buffer + offset, 4 ); offset += 4;
printf(" results->error_flag=%d\r\n", results->error_flag );
printf(" results->res_num=%d\r\n", results->res_num );
int i = 0;
for( i = 0; i < results->res_num; i++ ){
struct res_info* res_info = unpack_res_info( buffer + offset, 0 );
sql_results_set_res_info( results, i, res_info );
offset += res_info_total_len( res_info );
}
printf(" unpack_sql_results_set5\r\n" );
printf("end unpack_sql_results_set\r\n" );
return results;
}
void process_result_set( MYSQL* mysql, MYSQL_RES * res, struct res_info* res_info ){
my_ulonglong rownum = mysql_num_rows( res );
int fieldcount = mysql_field_count(mysql);
unsigned long *lengths;
lengths = mysql_fetch_lengths(res);
MYSQL_FIELD *field = NULL;
MYSQL_ROW row;
res_info->row_num = rownum;
res_info->col_num = fieldcount;
res_info->file_data_count = fieldcount*rownum;
int cur_field = 0;
while((field = mysql_fetch_field(res)) &&field != NULL ) {
struct col_def* col_def = create_col_def( );
col_def->col_name_len = strlen( field->name );
col_def->col_name = malloc( sizeof( col_def->col_name_len + 1 ) );
memset( col_def->col_name, 0, col_def->col_name_len+1);
memcpy( col_def->col_name, field->name, col_def->col_name_len );
//col_def->col_name = field->name;
col_def->field_type = field->type;
res_info_set_col_def( res_info, cur_field, col_def );
cur_field++;
}
int currow = 0;
int irow = 0;
int icol = 0;
int cur_field_count = 0;
while( currow < rownum ){
row = mysql_fetch_row(res);
lengths = mysql_fetch_lengths(res);
for( icol = 0; icol < fieldcount; icol++ ){
int len = lengths;
char* data = row[ icol ];
printf("irow=%d icol=%d len=%d data=%s\n", currow, icol, len, data );
struct field_data* field_data = create_field_data( );
field_data->data_len = len;
field_data->data = malloc( sizeof( len + 1 ) );
memset( field_data->data, 0, len+1);
memcpy( field_data->data, data, len );
//field_data->data = data;
res_info_set_field_data( res_info, cur_field_count, field_data );
cur_field_count++;
}
currow++;
}
}
struct sql_results* exe_sql_muti( MYSQL* mysql, char* sql ) {
struct sql_results* response_result = sql_results_create( );
int status = 0;
int cur_res_info_num = 0;
status = mysql_query(mysql,sql );
if (status){
printf("exe_sql mysql_query error ==========================\r\n");
response_result->error_flag = 1;
return response_result;
}
MYSQL_RES *result;
/* process each statement result */
do {
struct res_info* res_info = create_res_info( );
/* did current statement return data? */
result = mysql_store_result(mysql);
if (result){
/* yes; process rows and free the result set */
process_result_set(mysql, result, res_info );
printf("record set\r\n");
//mysql_free_result(result);
}
else { /* no result set or error */
if (mysql_field_count(mysql) == 0){
int affect_rows = (int)mysql_affected_rows(mysql);
res_info->affect_rows = affect_rows;
printf("%d rows affected\n", affect_rows );
}
else{/* some error occurred */
response_result->error_flag = 1;
printf("Could not retrieve result set\n");
break;
}
}
response_result->res_num = cur_res_info_num + 1;
sql_results_set_res_info( response_result, cur_res_info_num++, res_info );
/* more results? -1 = no, >0 = error, 0 = yes (keep looping) */
if ((status = mysql_next_result(mysql)) > 0){
response_result->error_flag = 1;
printf("Could not execute statement\n");
}
} while (status == 0);
return response_result;
}
struct sql_results* exe_sql_single( MYSQL* mysql, char* sql ) {
struct sql_results* response_result = sql_results_create( );
int status = 0;
int cur_res_info_num = 0;
status = mysql_query(mysql,sql );
if (status){
response_result->error_flag = 1;
return response_result;
}
MYSQL_RES *result;
/* process each statement result */
struct res_info* res_info = create_res_info( );
/* did current statement return data? */
result = mysql_store_result(mysql);
if (result){
/* yes; process rows and free the result set */
process_result_set(mysql, result, res_info );
printf("record set\r\n");
mysql_free_result(result);
}
else { /* no result set or error */
if (mysql_field_count(mysql) == 0){
int affect_rows = (int)mysql_affected_rows(mysql);
res_info->affect_rows = affect_rows;
printf("%d rows affected\n", affect_rows );
}
else{/* some error occurred */
response_result->error_flag = 1;
printf("Could not retrieve result set\n");
}
}
response_result->res_num = cur_res_info_num + 1;
sql_results_set_res_info( response_result, cur_res_info_num++, res_info );
return response_result;
}
struct res_info*exe_sql( MYSQL* mysql, char* sql ) {
struct res_info* res_info = create_res_info( );
int status = 0;
int cur_res_info_num = 0;
status = mysql_query(mysql,sql );
if (status){
res_info->error_code = 1;
return res_info;
}
MYSQL_RES *result;
/* process each statement result */
/* did current statement return data? */
result = mysql_store_result(mysql);
if (result){
/* yes; process rows and free the result set */
process_result_set(mysql, result, res_info );
printf("record set\r\n");
mysql_free_result(result);
}
else { /* no result set or error */
if (mysql_field_count(mysql) == 0){
int affect_rows = (int)mysql_affected_rows(mysql);
res_info->affect_rows = affect_rows;
printf("%d rows affected\n", affect_rows );
}
else{/* some error occurred */
res_info->error_code = 1;
printf("Could not retrieve result set\n");
}
}
//response_result->res_num = cur_res_info_num + 1;
//sql_results_set_res_info( response_result, cur_res_info_num++, res_info );
return res_info;
}
struct res_info* exe_sql_make_buffer( MYSQL* mysql, char* sql, char* buffer ) {
struct res_info* res_info = create_res_info( );
int status = 0;
int cur_res_info_num = 0;
status = mysql_query(mysql,sql );
if (status){
res_info->error_code = 1;
pack_res_info( res_info, buffer );
return res_info;
}
MYSQL_RES *result;
/* process each statement result */
/* did current statement return data? */
result = mysql_store_result(mysql);
if (result){
/* yes; process rows and free the result set */
process_result_set(mysql, result, res_info );
printf("record set\r\n");
pack_res_info( res_info, buffer );
mysql_free_result(result);
return res_info;
}
else { /* no result set or error */
if (mysql_field_count(mysql) == 0){
int affect_rows = (int)mysql_affected_rows(mysql);
res_info->affect_rows = affect_rows;
printf("%d rows affected\n", affect_rows );
}
else{/* some error occurred */
res_info->error_code = 1;
printf("Could not retrieve result set\n");
}
}
//response_result->res_num = cur_res_info_num + 1;
//sql_results_set_res_info( response_result, cur_res_info_num++, res_info );
pack_res_info( res_info, buffer );
return res_info;
}
void sql_results_makehead( struct sql_results* results, char* buffer ){
int offset = 0;
memcpy( buffer + offset, &results->error_flag, 4); offset += 4;
memcpy( buffer + offset, &results->res_num, 4);
}
struct sql_results* exe_sql_muti_makebuffer( MYSQL* mysql, char* sql, char* buffer ) {
struct sql_results* response_result = sql_results_create( );
int status = 0;
int offset = 8;
int result_num = 0;
int cur_res_info_num = 0;
status = mysql_query(mysql,sql );
if (status){
printf("exe_sql mysql_query error ========================== errormsg=%s\r\n", mysql_error(mysql) );
response_result->error_flag = 1;
response_result->res_num = 0;
sql_results_makehead( response_result, buffer );
return response_result;
}
MYSQL_RES *result;
/* process each statement result */
do {
struct res_info* res_info = create_res_info( );
/* did current statement return data? */
result = mysql_store_result(mysql);
if (result){
/* yes; process rows and free the result set */
process_result_set(mysql, result, res_info );
pack_res_info( res_info, buffer+offset );
printf("record set\r\n");
mysql_free_result(result);
}
else { /* no result set or error */
if (mysql_field_count(mysql) == 0){
int affect_rows = (int)mysql_affected_rows(mysql);
res_info->affect_rows = affect_rows;
printf("%d rows affected\n", affect_rows );
pack_res_info( res_info, buffer+offset );
}
else{/* some error occurred */
response_result->error_flag = 1;
printf("Could not retrieve result set\n");
break;
}
}
response_result->res_num = cur_res_info_num + 1;
sql_results_set_res_info( response_result, cur_res_info_num++, res_info );
offset += res_info_total_len( res_info );
/* more results? -1 = no, >0 = error, 0 = yes (keep looping) */
if ((status = mysql_next_result(mysql)) > 0){
response_result->error_flag = 1;
printf("Could not execute statement\n");
}
} while (status == 0);
sql_results_makehead( response_result, buffer );
return response_result;
}
MYSQL mysql;
MYSQL_RES *res;
MYSQL_ROW row;
void run_req( ){
{
printf("exe_sql........\r\n");
char* testmsg = (char*)malloc( sizeof(20000));
//char testmsg;
struct sql_results* results = exe_sql_muti_makebuffer( &mysql, "DROP TABLE IF EXISTS test_table;\
CREATE TABLE test_table(id INT);\
INSERT INTO test_table VALUES(10);\
UPDATE test_table SET id=20 WHERE id=10;\
SELECT * FROM test_table;\
select * from Persons;",
testmsg );
//struct sql_results* results = exe_sql( &mysql, "select * from persons;" );
sql_results_set_total_debug( results );
printf("end exe_sql........\r\n");
int total_len = sql_results_set_total_len( results );
printf("end exe_sql........len=%d\r\n", total_len );
sql_results_destroy( results );
struct sql_results* results_ = sql_results_create( );
printf("begin unpack_sql_results_set........\r\n");
struct sql_results* result_ret = unpack_sql_results_set( testmsg, total_len );
printf("end unpack_sql_results_set........\r\n");
sql_results_set_total_debug( result_ret );
sql_results_destroy( result_ret );
free( testmsg );
printf("end ........\r\n");
}
}
int main()
{
mysql_library_init(0, NULL, NULL );
mysql_init(&mysql);
if(!mysql_real_connect(&mysql,"127.0.0.1","root",
"","test",3306,NULL,CLIENT_MULTI_RESULTS|CLIENT_MULTI_STATEMENTS))
{
//CLIENT_MULTI_RESULTS|CLIENT_MULTI_STATEMENTS
printf("Error connecting to database:%s\n",mysql_error(&mysql));
}
else
printf("Connected........\r\n");
char *query = "select * from Persons;";
int t,r;
int j = 0;
for( j = 0; j < 30; j++ ){
printf("run_req........ ==================== ------------------ ************* j = %d \r\n", j );
malloc( 1000 );
run_req( );
}
return 0;
}
Segmentation fault: 11
run_req函数
char* testmsg = (char*)malloc( sizeof(20000));改为数组形式 比如char testmsg[2000], 则不会崩溃。
请赐教
页:
[1]