c - 使用 mysql_stmt_prepare 时如何引用 char* 而不是使用 char[]

标签 c

当尝试使用 C 语言使用绑定(bind)参数插入多个记录时,我无法使用 char * str_data 使其工作,然后使用 strdup 的 malloc 设置“测试字符串”。我必须定义char str_data[50]。如果我尝试使用 char * str_data 和 str_data = strdup("teststring") ,它会用随机字节填充 MySQL。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <my_global.h>
#include <mysql.h>

int main(void)
{
    MYSQL *con;
    con = mysql_init(NULL);

    my_bool reconnect = 1;
    mysql_options(con, MYSQL_OPT_RECONNECT, &reconnect);

    if (mysql_real_connect(con, "127.0.0.1", "hidden", "hidden", "hidden", 0, NULL, 0) == NULL) {
        fprintf(stderr, "%s\n", mysql_error(con));
        mysql_close(con);
        exit(0);
    }

    MYSQL_STMT *stmt;
    MYSQL_BIND ps_params[1];
    char str_data[50];
    unsigned long str_length;

    stmt = mysql_stmt_init(con);
    mysql_stmt_prepare(stmt, "INSERT INTO `test` (two) VALUES (?)", strlen("INSERT INTO `test` (two) VALUES (?)"));
    memset(ps_params, 0, sizeof(ps_params));

    ps_params[0].buffer_type = MYSQL_TYPE_STRING;
    ps_params[0].buffer = (char *)&str_data;
    ps_params[0].buffer_length = 50;
    ps_params[0].length = &str_length;
    ps_params[0].is_null = 0;

    mysql_stmt_bind_param(stmt, ps_params);

    str_length = strlen("test string");
    strcpy(str_data, "test string");
    mysql_stmt_execute(stmt);

    mysql_close(con);

}

有人可以向我解释为什么使用 char * str_datastr_data = strdup("teststring") 会导致 MySQL 读取乱码吗?

编辑:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <my_global.h>
#include <mysql.h>

int main(void)
{
    MYSQL *con;
    con = mysql_init(NULL);

    my_bool reconnect = 1;
    mysql_options(con, MYSQL_OPT_RECONNECT, &reconnect);

    if (mysql_real_connect(con, "127.0.0.1", "hidden", "hidden", "hidden", 0, NULL, 0) == NULL) {
        fprintf(stderr, "%s\n", mysql_error(con));
        mysql_close(con);
        exit(0);
    }

    MYSQL_STMT *stmt;
    MYSQL_BIND ps_params[1];
    char * str_data;
    unsigned long str_length;

    stmt = mysql_stmt_init(con);
    mysql_stmt_prepare(stmt, "INSERT INTO `test` (two) VALUES (?)", strlen("INSERT INTO `test` (two) VALUES (?)"));
    memset(ps_params, 0, sizeof(ps_params));

    ps_params[0].buffer_type = MYSQL_TYPE_STRING;
    ps_params[0].buffer = (char *)&str_data;
    ps_params[0].buffer_length = (strlen("test string") + 1);
    ps_params[0].length = &str_length;
    ps_params[0].is_null = 0;

    mysql_stmt_bind_param(stmt, ps_params);

    str_length = strlen("test string");
    str_data = strdup("test string");
    mysql_stmt_execute(stmt);

    mysql_close(con);

}

数据库结果:Ð|D =N_

结果为printf("'%s'\n", str_data):'测试字符串'

我认为这与 ps_params[0].buffer = (char *)&str_data; 作为指针有关

最佳答案

这是代码中令人反感的部分:

ps_params[0].buffer = (char *)&str_data;

.buffer 应该指向内存缓冲区,但它指向一个(未初始化的)指针。 事实上,您正在使用类型转换来消除编译器警告,这应该暗示出现了非常错误的情况。 在任何情况下都永远不要使用类型转换,除非您比编译器更了解发生了什么!

因此,如果str_data指向缓冲区,只需使用str_data初始化ps_params[0].buffer code> 而不是 str_data地址.buffer 应该指向 str_data 指向的“同一事物”,而不是str_data 本身。像这样:

ps_params[0].buffer = str_data;

现在的问题是,您还没有初始化str_data。它指向垃圾,所以现在 ps_params[0].buffer 也指向垃圾。因此,您必须将 str_data 的初始化移至 ps_params[0].buffer 的赋值之前:

char * str_data = strdup("test string");
unsigned long str_length = strlen(str_data);

stmt = mysql_stmt_init(con);
mysql_stmt_prepare(stmt, "INSERT INTO `test` (two) VALUES (?)", strlen("INSERT INTO `test` (two) VALUES (?)"));
memset(ps_params, 0, sizeof(ps_params));

ps_params[0].buffer_type = MYSQL_TYPE_STRING;
ps_params[0].buffer = str_data;
ps_params[0].buffer_length = str_len + 1;
ps_params[0].length = &str_length;
ps_params[0].is_null = 0;

mysql_stmt_bind_param(stmt, ps_params);

mysql_stmt_execute(stmt);

// `strdup` calls `malloc`, so we have to free the buffer after use
free(str_data); 

mysql_close(con);

添加运行时错误检查作为读者的练习

关于c - 使用 mysql_stmt_prepare 时如何引用 char* 而不是使用 char[],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56938848/

相关文章:

python - 什么是 C 相当于 python 的 map()

c - svn_client_checkout3 因 EXC_BAD_ACCESS 而崩溃

c - 最大数量 "C"

c - 在源代码中查找 main 函数

c - 无锁链表的性能比有锁链表差

c - c中一个简单的shell程序中的历史实现

使用二分搜索检查排序的非顺序数组是否有重复项?

c - 什么是轻量级跨平台WAV播放库?

c - 使用 libcURL 发送不带数据的 PUT 请求

c - 如何在c中打印指针?