使用MariaDB的C程序调用mysql_query触发SIGSEGV错误求助
问题排查与解决建议
以下是针对代码中导致SIGSEGV错误的关键问题分析及解决方法:
1. 全局变量类型不匹配引发参数传递错误
全局变量声明存在类型错误:
char * drawing_number, layoutID;
这里layoutID被声明为char类型,但在sprintf中使用了长整型格式符%ld:
sprintf(query,"SELECT name,wd,ht FROM pagelayouts WHERE drawing=%s AND handle=%ld;",drawing_number,layoutID);
将char类型作为long参数传递会打乱栈帧布局,直接破坏后续函数调用的内存结构,触发段错误。
修复:
修正layoutID的类型与格式符匹配:
char *drawing_number; long layoutID;
2. 内存分配计算错误导致堆溢出
initialize_database函数中内存分配逻辑错误:
char * Dname=(char *)malloc(strlen(dBase+2));
strlen(dBase+2)是计算指针偏移2字节后的字符串长度,而非原字符串长度加2。这会导致分配的内存远小于实际需求,后续sprintf写入时会溢出堆内存,破坏堆结构,间接引发数据库操作时的内存访问异常。
修复:
正确计算所需内存大小:
// "prefix"共6个字符,加原字符串长度加终止符,总长度为strlen(dBase)+7 char *Dname = (char *)malloc(strlen(dBase) + 7); snprintf(Dname, strlen(dBase)+7, "prefix%s", dBase);
3. 函数定义语法错误(可能破坏代码结构)
update_layout_database函数缺少起始大括号:
void update_layout_database() char query[255];
即便编译器未报错,也会导致函数内变量布局异常,引发未知内存错误。
修复:
补全函数起始大括号:
void update_layout_database() { char query[255]; // 后续代码 }
4. 缓冲区溢出风险
query数组仅255字节,当drawing_number较长或浮点数字符串表示过长时,sprintf会溢出缓冲区,破坏栈上的sqlconnect等变量,导致调用mysql_query时访问非法内存。
修复:
改用snprintf限制写入长度:
snprintf(query, sizeof(query), "SELECT name,wd,ht FROM pagelayouts WHERE drawing=%s AND handle=%ld;", drawing_number, layoutID);
UPDATE语句同理:
snprintf(query, sizeof(query), "UPDATE pagelayouts SET X=%f, Y=%f,wd=%f,ht=%f WHERE drawing=%s AND handle=%ld", Extents[0], Extents[1], wd, ht, drawing_number, layoutID);
5. 未检查数据库操作返回值与资源泄漏
mysql_query调用后未检查返回值,若查询失败,mysql_store_result会返回NULL,后续mysql_fetch_row访问空指针会崩溃。- 未调用
mysql_free_result释放结果集,长期运行会引发内存泄漏。
修复:
添加返回值检查与资源释放:
int res = mysql_query(sqlconnect, query); if (res != 0) { fprintf(stderr, "Query failed: %s\n", mysql_error(sqlconnect)); return; } MYSQL_RES *result = mysql_store_result(sqlconnect); if (result == NULL) { fprintf(stderr, "Store result failed: %s\n", mysql_error(sqlconnect)); return; } row = mysql_fetch_row(result); // 业务逻辑 mysql_free_result(result); // 释放结果集
额外排查步骤
- 在GDB中
mysql_query调用瞬间,再次确认sqlconnect指针的合法性,避免被溢出操作覆盖。 - 检查
drawing_number是否为合法的以\0终止的字符串,排除野指针或非终止字符串导致的内存读取错误。 - 确认
Extents数组未被越界访问,避免栈内存被破坏。
内容的提问来源于stack exchange,提问作者Dave Coventry
相关产品推荐
相关产品推荐

