调用free(_mult)致程序崩溃,free(_add)正常的C语言问题排查
问题:free(_mult)崩溃但free(_add)正常的原因分析
本人英文不佳,是C语言新手,正在实现2-10进制下两个数的求和与乘法功能。程序输出结果正确,但调用free(_mult)时程序崩溃,调用free(_add)却无异常,对此感到困惑,特附上代码寻求原因:
int * convert(long long int x, int base, int *arr) // convert the number to base b and return the array with length 64 { int i = 63; while(x != 0) { arr[i] = x % base; x /= base; i--; } for(int j=i; j>=0; j--) arr[j] = 0; return arr; } int * add(int *n, int *m, int base, int * arr) // calculate the summation bit by bit. { int carry = 0, sum; int v1, v2; for(int i=63; i>=0; i--) { v1 = n[i]; v2 = m[i]; sum = v1 + v2 + carry; carry = sum / base; arr[i] = sum % base; } return arr; } int * mult(int *n, int*m, int base, int * arr) // calculate the multiplication bit by bit. { for(int i=0; i<64; i++) arr[i] = 0; int ind_m = 64; int index = 64; while(ind_m != 0) { int ind_n = 64; int carry = 0; int ind_arr, res; ind_arr = index - 1 - (64 - ind_m); while(ind_n != 0) { res = ( m[ind_m-1] * n[ind_n-1] ) + arr[ind_arr] + carry; carry = res / base; arr[ind_arr] = res % base; ind_arr--; ind_n--; } arr[ind_arr] += carry; ind_m--; } return arr; } int main() { int b; long long int x, y; scanf("%d%lld%lld", &b, &x, &y); int *n = malloc(sizeof(int)*(64));//64 bit for digits int *m = malloc(sizeof(int)*(64)); for(int i=0; i<64; i++) n[i] = 0; for(int i=0; i<64; i++) m[i] = 0; n = convert(x, b, n); m = convert(y, b, m); int *_add = malloc(sizeof(int)*(64)); _add = add(n, m, b, _add); free(_add); int *_mult = malloc(sizeof(int)*(64)); _mult = mult(n, m, b, _mult); free(_mult); free(n); free(m); return 0; }
问题原因与修复方案
崩溃的核心原因是mult函数中存在数组越界访问,破坏了malloc分配内存块的元数据,导致free时触发错误。
具体越界点分析
在mult函数的内层循环中:
当ind_m递减到1时,ind_arr初始值为63,随后内层ind_n从64循环到0,每次循环ind_arr减1。当循环结束时,ind_arr会变成63 - 64 = -1,此时执行arr[ind_arr] += carry,也就是访问arr[-1]——这属于非法的越界访问,会覆盖malloc内存块头部的元数据(比如内存大小标记),导致后续free(_mult)时系统无法识别合法的内存块,直接崩溃。
而add函数的循环始终在arr[0]到arr[63]的合法范围内访问,没有越界,所以free(_add)正常。
修复方法
修改mult函数中处理carry的逻辑,确保数组访问不越界:
// 替换原有的arr[ind_arr] += carry; if (ind_arr >= 0) { arr[ind_arr] += carry; }
或者重新梳理乘法的索引计算逻辑,从根源上避免ind_arr变为负数。
额外建议
- 用
calloc代替malloc加循环初始化,calloc会自动将内存初始化为0,代码更简洁:int *n = calloc(64, sizeof(int)); - 调试数组越界问题时,可用gcc的地址 sanitizer(编译时加
-fsanitize=address参数),能快速定位越界位置。
内容的提问来源于stack exchange,提问作者jamie
相关产品推荐
相关产品推荐

