munmap_chunk(): invalid pointer错误排查:矩阵拷贝场景下内存正确释放方法
解决memcpy导致的munmap_chunk()错误与内存释放问题
我帮你排查下问题所在,其实错误的根源并不是memcpy修改了源指针——memcpy根本不会改动源地址的指针值,真正的问题是你在memcpy里用错了内存长度参数,导致堆内存溢出,破坏了堆的元数据,最终在free的时候触发了错误。
核心错误分析
看你的memcpy调用:
memcpy( submat[0] , mat[0], sub_mtrx_size* sizeof(&submat) );
这里的sizeof(&submat)是致命错误:submat是int**类型,&submat就是int***(指向二级指针的指针),它的大小在64位系统是8字节,32位是4字节。而你需要复制的是int类型的数据,每个int通常是4字节。
你要复制4个int,正确的长度应该是sub_mtrx_size * sizeof(int)(也就是4*4=16字节),但你现在计算的是4*8=32字节,远远超出了submat[i]分配的内存(你给submat[k]分配的是4*sizeof(int)=16字节)。这种堆溢出会破坏相邻堆块的管理元数据,当后续执行free(mat[i])时,堆管理器检测到元数据损坏,就抛出了munmap_chunk()错误。
修复方案
1. 修正memcpy的长度参数
把sizeof(&submat)换成sizeof(int),或者更安全的sizeof(*submat[0])(通过指针指向的元素类型来获取大小,即使后续修改类型也不用改这里)。
2. 用循环替代重复的memcpy调用
你手动写了4次memcpy,换成循环更简洁,也能避免重复代码出错:
for (int i = 0; i < sub_mtrx_size; i++) { // 用sizeof(*submat[i])确保类型匹配 memcpy(submat[i], mat[i], sub_mtrx_size * sizeof(*submat[i])); }
3. 完整修正后的main函数
// Main function int main (void){ const int n = 8; int sub_mtrx_size = n/2; int ** mat = malloc(sizeof(int*) * n); int ** submat = malloc(sizeof(int*) * sub_mtrx_size); // 直接用sub_mtrx_size更清晰 for (int k = 0; k < n; k++) { mat[k] = malloc(sizeof(int) * n); if ( k < sub_mtrx_size){ submat[k] = malloc(sizeof(int) * sub_mtrx_size); } } init (mat,n,n); // 替换为循环的memcpy for (int i = 0; i < sub_mtrx_size; i++) { memcpy(submat[i], mat[i], sub_mtrx_size * sizeof(*submat[i])); } print(submat, sub_mtrx_size, sub_mtrx_size); // 正确释放内存 for (int i = 0; i < n; i++) { free(mat[i]); // 现在可以安全释放了 if ( i < sub_mtrx_size){ free(submat[i]); } } free (mat); free (submat); return 0; }
额外注意事项
- 堆溢出的错误往往不会立刻显现,可能在后续的内存操作(比如
free)才触发,排查时要重点检查所有内存复制、写入的边界是否正确。 - 分配内存时尽量用变量(比如
sub_mtrx_size)代替硬编码的数字,减少维护成本和出错几率。 - 可以用
valgrind这类工具检测内存错误,它能直接定位到堆溢出的位置,帮助快速排查问题。
内容的提问来源于stack exchange,提问作者user206904
相关产品推荐
相关产品推荐

