You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用mysql_init时覆盖字符数组的问题求助

问题根源与解决方案

这问题的核心是内存越界写入导致的未定义行为,咱们一步步拆解来看:

1. 最致命的错误:单个字符被当作字符串缓冲区使用

你在main里定义的char uid;是单个字符变量,它仅占用1字节内存,但你的get_uid函数却把它当成能存储多字符的字符串数组来写入。比如当argv[1]是389302-8232时,get_uid会往&uid(单个字符的内存地址)连续写入'3'、'8'、'9'、'3'、'0'、'2',最后再加'\0'——这一共是7字节的数据,远超uid的1字节容量,直接触发越界写入相邻内存区域。

这种越界属于C语言里的未定义行为:一开始输出正常只是运气好,相邻内存还没被修改;但当你调用mysql_init(&conn)时,MYSQL类型的conn变量刚好存在uid的相邻内存区域,初始化conn时覆盖了之前越界写入的字符,所以后续输出&uid就只剩下第一个字符了——后面的字节已经被conn的初始化数据冲掉。

2. 为什么调用mysql_close会触发段错误?

当你用单个char uid时,越界写入的内容已经破坏了MYSQL conn结构体的内部数据,导致mysql_close访问了非法内存地址,直接触发段错误。而改成malloc分配足够内存后,get_uid的写入不再越界,不会破坏其他变量的内存,自然就不会触发段错误了。

正确的修正方案

方案一:使用固定大小的字符数组(推荐,适合已知最大长度的场景)

如果能提前确定uid的最大长度,直接定义足够大的数组(要留1字节存字符串结束符'\0'):

// 假设uid最长不超过20个字符,定义21字节的数组
char uid[21];
get_uid(argv[1], uid);

方案二:动态分配内存(你当前使用的方式)

注意malloc时要额外加1字节,用来存储字符串结束符,避免再次越界:

// strlen(argv[1])是原字符串长度,+1是为了存'\0'
char *uid = malloc(strlen(argv[1]) + 1);
if (uid == NULL) {
    // 必须处理内存分配失败的情况
    perror("malloc failed");
    return 1;
}
get_uid(argv[1], uid);
// 使用uid进行后续操作...
free(uid);

额外优化:给get_uid加安全限制

可以给get_uid增加一个参数,限制目标缓冲区的最大长度,彻底避免即使传入数组也可能出现的越界:

void get_uid(char *src, char *dst, size_t max_dst_len) { 
    int i, len, count = 0; 
    len = strlen(src); 
    // 循环条件增加缓冲区长度限制,预留1字节存'\0'
    for(i = 0; i != len && count < max_dst_len - 1; i++) { 
        if(src[i] == '-') { 
            break; 
        } 
        dst[count] = src[i]; 
        count++; 
    } 
    dst[count] = '\0'; 
}

调用时传入缓冲区大小即可:

  • 数组场景:get_uid(argv[1], uid, sizeof(uid));
  • 动态分配场景:get_uid(argv[1], uid, strlen(argv[1])+1);

内容的提问来源于stack exchange,提问作者John

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:23:13