MySQL社区

 找回密码
 注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

搜索
查看: 2191|回复: 0
打印 上一主题 下一主题

mysql c api 多结果集时,上下文分配空间,内存访问越界

[复制链接]
跳转到指定楼层
1#
发表于 2014-9-1 00:35:27 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
最近想做一个访问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[100];        // alloc
        int file_data_count;
        struct field_data* file_data[100]; // 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 ){
        int  i = 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 );
}


int  res_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[index] = 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[index] = 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_info  def->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_info  def->data=%s \r\n", buffer + offset );
                offset += def->data_len;       
        }
        printf("pack_res_info  write 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_info  read buff = %d \r\n", offset );
        return res_info;
}


struct sql_results {
        struct res_info*         res_infos[10];        //
        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_results  cur 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[icol];
                         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[20000];
                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], 则不会崩溃。




请赐教

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
收藏收藏 分享淘帖 顶1 踩
您需要登录后才可以回帖 登录 | 注册

本版积分规则

QQ|申请友链|小黑屋|Archiver|手机版|MySQL社区 ( 京ICP备07012489号   
联系人:周生; 联系电话:13911732319

GMT+8, 2024-5-26 02:03 , Processed in 0.064551 second(s), 23 queries , Gzip On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表