c语言调用mysql绑定数据时发生的严重问题,求解决

时间:2022-01-24 23:33:35
我在开发C+MYSQL 时,便用的是MYSQL预处理,但在执行过程中发生了奇怪问题
下面是精简后的版本,实际程序代码太多

char *table="db_sys_io";
MYSQL_BIND params[2];
    memset(params,'\0',2);
        params[0].buffer="set names";
        params[0].length=strlen("set names");
        params[0].buffer_length=strlen("set names");
        params[0].buffer_type=MYSQL_TYPE_STRING;

        params[1].buffer="set namesss";
        params[1].length=strlen("set namesss");
        params[1].buffer_length=strlen("set namesss");
        params[1].buffer_type=MYSQL_TYPE_STRING;
    char sql[300];
    memset(sql,'\0',300);
    sprintf(sql,"update %s set event=?,details=? where id=1",table);
    printf("%s",sql);
    if(mysql_stmt_prepare(stmt, sql, strlen(sql))){
        fprintf(stderr, "mysql_stmt_prepare: %s\n", mysql_stmt_error(stmt));
        return 0;
    }

    int binderror=mysql_stmt_bind_param(stmt,params);
    if(binderror){
       fprintf(stderr, "mysql stmt error: %s\n", mysql_stmt_error(stmt));
    }
    int result=mysql_stmt_execute(stmt);
    if(result){
        fprintf(stderr, " mysql_stmt_execute(), 1 failed\n");
        fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
    }

运行时,程序直接挂掉
检查MYSQL日志,仅执行到了下面
Prepare update db_sys_io set event=?,details=? where id=1

做相应的调试
注释掉后面的mysql_stmt_exec,则没有崩溃,但是程序没有执行完成
或者不用mysql_bind功能,程序也能执行,但后期显然是存在很多问题的

有哪位大侠知道问题何在啊!!!!不胜感激

10 个解决方案

#1


params[0].buffer params[1].buffer 

这个buff不可以是常量的地址,常量地址不可写

#2


params[0].length  params[1].length

这个length  是指针, 是unsigned long *, 你直接赋值为strlen("XXX") 显然也是不对的,它必须赋值为一个变量的地址

#3


你可以参考这里的  DBOperator::BindString

#4


params[0].buffer="set names";
        params[0].length=strlen("set names");
        params[0].buffer_length=strlen("set names");
        params[0].buffer_type=MYSQL_TYPE_STRING;

        params[1].buffer="set namesss";
        params[1].length=strlen("set namesss");
        params[1].buffer_length=strlen("set namesss");
        params[1].buffer_type=MYSQL_TYPE_STRING;

你能贴出这些数据结构的声明和定义吗?
调用mysql的函数应该是没问题,问题可能是出在参数的赋值方面。

#5


上面是不完整的程序
我定义了一个函数,用来修改数据库
方法如下
int DLL_EXPORT updateDB(MYSQL_STMT *stmt,char *table,char *update[][2],int updateRows,char *where[][3],int whereRows){
    if(updateRows%2!=0 || whereRows%3!=0){
        return 0;
    }
    int i=0,j=0;
    int updatelens=0;
    int wherelens=0;
    int urows=updateRows/2;
    int wrows=whereRows/3;
    while(i<urows){
        j=0;
        while(j<3){
            updatelens+=strlen(update[i][j]);
            j++;
        }
        i++;
    }


    i=0;j=0;
    while(i<wrows){
        j=0;
        while(j<3){
            wherelens+=strlen(where[i][j]);
            j++;
        }
        i++;
    }

    int alllen=strlen("update")+strlen("set")+strlen("where")+20+strlen(table)+updatelens+wherelens;
    char sql[alllen];
    memset(sql,0,alllen);
    int offset=0;
    offset+=sprintf(sql+offset,"update %s set ",table);
    i=0,j=0;
    int stoprows=urows-1;
    MYSQL_BIND params[urows];
    memset(params,'\0',urows);
    while(i<urows){
        offset+=sprintf(sql+offset,"%s=%s",update[i][0],"?");
        if(i<stoprows){
            offset+=sprintf(sql+offset,"%s",",");
        }
        params[i].buffer=update[i][1];
        params[i].length=strlen(update[i][1]);
        params[i].buffer_length=strlen(update[i][1]);
        params[i].buffer_type=MYSQL_TYPE_STRING;
        i++;
    }


    offset+=sprintf(sql+offset," %s ","where");
    stoprows=wrows-1;
    while(j<wrows){
        offset+=sprintf(sql+offset,"%s %s \"%s\"",where[j][0],where[j][1],where[j][2]);
        if(j<stoprows){
            offset+=sprintf(sql+offset,"%s"," && ");
        }
        j++;
    }

    if(mysql_stmt_prepare(stmt, sql, strlen(sql))){
        fprintf(stderr, "mysql_stmt_prepare: %s\n", mysql_stmt_error(stmt));
        return 0;
    }

    int binderror=mysql_stmt_bind_param(stmt,params);
    if(binderror){
       fprintf(stderr, "mysql stmt error: %s\n", mysql_stmt_error(stmt));
    }
/*
    i=0;
    while(i<urows){
        printf("%s %d \n",params[i].buffer,params[i].buffer_length);
        i++;
    }
    */
    int result=mysql_stmt_execute(stmt);
    if(result){
        fprintf(stderr, " mysql_stmt_execute(), 1 failed\n");
        fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
    }
    return !result;
}

下面是调用方法
char *table="db_sys_io";
    char *update[][2]={{"event","i will test it"},{"details","yes,i will test it"}};
    char *where[][3]={{"event","=","test"},{"details","=","test"}};
    int result=updateDB(stmt,table,update,sizeof(update)/sizeof(char *),where,sizeof(where)/sizeof(char *));

#6


另外补充一句,我写了插入数据的功能,和这个类似,是可以正常执行的,但就这个update,一直不成功!!!!没有找到原因啊~~~~

#7


引用 6 楼 mysteo 的回复:
另外补充一句,我写了插入数据的功能,和这个类似,是可以正常执行的,但就这个update,一直不成功!!!!没有找到原因啊~~~~


执行不成功, 总会有错误信息的, 你的错误信息是什么呢

#8


执行到
    int result=mysql_stmt_execute(stmt);
直接挂掉崩溃了

我用调试工具,提示的是:no symbol table info available

我开始怀疑是stmt通过传值后,丢失了,但我在这个方法里执行添加动作是成功的,就UPDATE不成功,没有搞明白

#9


c语言调用mysql绑定数据时发生的严重问题,求解决c语言调用mysql绑定数据时发生的严重问题,求解决

#10


发现问题:stmt的地址被修改了~~~~

#1


params[0].buffer params[1].buffer 

这个buff不可以是常量的地址,常量地址不可写

#2


params[0].length  params[1].length

这个length  是指针, 是unsigned long *, 你直接赋值为strlen("XXX") 显然也是不对的,它必须赋值为一个变量的地址

#3


你可以参考这里的  DBOperator::BindString

#4


params[0].buffer="set names";
        params[0].length=strlen("set names");
        params[0].buffer_length=strlen("set names");
        params[0].buffer_type=MYSQL_TYPE_STRING;

        params[1].buffer="set namesss";
        params[1].length=strlen("set namesss");
        params[1].buffer_length=strlen("set namesss");
        params[1].buffer_type=MYSQL_TYPE_STRING;

你能贴出这些数据结构的声明和定义吗?
调用mysql的函数应该是没问题,问题可能是出在参数的赋值方面。

#5


上面是不完整的程序
我定义了一个函数,用来修改数据库
方法如下
int DLL_EXPORT updateDB(MYSQL_STMT *stmt,char *table,char *update[][2],int updateRows,char *where[][3],int whereRows){
    if(updateRows%2!=0 || whereRows%3!=0){
        return 0;
    }
    int i=0,j=0;
    int updatelens=0;
    int wherelens=0;
    int urows=updateRows/2;
    int wrows=whereRows/3;
    while(i<urows){
        j=0;
        while(j<3){
            updatelens+=strlen(update[i][j]);
            j++;
        }
        i++;
    }


    i=0;j=0;
    while(i<wrows){
        j=0;
        while(j<3){
            wherelens+=strlen(where[i][j]);
            j++;
        }
        i++;
    }

    int alllen=strlen("update")+strlen("set")+strlen("where")+20+strlen(table)+updatelens+wherelens;
    char sql[alllen];
    memset(sql,0,alllen);
    int offset=0;
    offset+=sprintf(sql+offset,"update %s set ",table);
    i=0,j=0;
    int stoprows=urows-1;
    MYSQL_BIND params[urows];
    memset(params,'\0',urows);
    while(i<urows){
        offset+=sprintf(sql+offset,"%s=%s",update[i][0],"?");
        if(i<stoprows){
            offset+=sprintf(sql+offset,"%s",",");
        }
        params[i].buffer=update[i][1];
        params[i].length=strlen(update[i][1]);
        params[i].buffer_length=strlen(update[i][1]);
        params[i].buffer_type=MYSQL_TYPE_STRING;
        i++;
    }


    offset+=sprintf(sql+offset," %s ","where");
    stoprows=wrows-1;
    while(j<wrows){
        offset+=sprintf(sql+offset,"%s %s \"%s\"",where[j][0],where[j][1],where[j][2]);
        if(j<stoprows){
            offset+=sprintf(sql+offset,"%s"," && ");
        }
        j++;
    }

    if(mysql_stmt_prepare(stmt, sql, strlen(sql))){
        fprintf(stderr, "mysql_stmt_prepare: %s\n", mysql_stmt_error(stmt));
        return 0;
    }

    int binderror=mysql_stmt_bind_param(stmt,params);
    if(binderror){
       fprintf(stderr, "mysql stmt error: %s\n", mysql_stmt_error(stmt));
    }
/*
    i=0;
    while(i<urows){
        printf("%s %d \n",params[i].buffer,params[i].buffer_length);
        i++;
    }
    */
    int result=mysql_stmt_execute(stmt);
    if(result){
        fprintf(stderr, " mysql_stmt_execute(), 1 failed\n");
        fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
    }
    return !result;
}

下面是调用方法
char *table="db_sys_io";
    char *update[][2]={{"event","i will test it"},{"details","yes,i will test it"}};
    char *where[][3]={{"event","=","test"},{"details","=","test"}};
    int result=updateDB(stmt,table,update,sizeof(update)/sizeof(char *),where,sizeof(where)/sizeof(char *));

#6


另外补充一句,我写了插入数据的功能,和这个类似,是可以正常执行的,但就这个update,一直不成功!!!!没有找到原因啊~~~~

#7


引用 6 楼 mysteo 的回复:
另外补充一句,我写了插入数据的功能,和这个类似,是可以正常执行的,但就这个update,一直不成功!!!!没有找到原因啊~~~~


执行不成功, 总会有错误信息的, 你的错误信息是什么呢

#8


执行到
    int result=mysql_stmt_execute(stmt);
直接挂掉崩溃了

我用调试工具,提示的是:no symbol table info available

我开始怀疑是stmt通过传值后,丢失了,但我在这个方法里执行添加动作是成功的,就UPDATE不成功,没有搞明白

#9


c语言调用mysql绑定数据时发生的严重问题,求解决c语言调用mysql绑定数据时发生的严重问题,求解决

#10


发现问题:stmt的地址被修改了~~~~