使用memcpy复制二维数组触发段错误的原因咨询
二维数组memcpy操作导致段错误的原因分析
我正在学习二维数组的操作以及memcpy的使用,编写了如下的array_test测试函数:
void array_test(void) { int arr[3][5] = {{0, 1, 1, 0, 1}, {1, 1, 1, 1, 1}, {1, 0, 0, 1, 0}}; for (size_t i = 0; i < 3; i++) { for (size_t j = 0; j < 5; j++) { printf("%d ", arr[i][j]); } printf("\n"); } int row = 3; int col = 5; int **arr2 = (int **)malloc(sizeof(int *) * row); if (!arr2) { printf("arr2 malloc failed\n"); exit(-1); } memset(arr2, 0, sizeof(int *) * row); for (int i = 0; i < row; i++) { arr2[i] = (int *)malloc(sizeof(int) * col); if (!arr2[i]) { printf("arr2[%d] malloc failed\n", i); exit(-1); } memset(arr2[i], 0, sizeof(int) * col); } for (size_t i = 0; i < 3; i++) { for (size_t j = 0; j < 5; j++) { printf("%d ", arr2[i][j]); } printf("\n"); } memcpy(arr2, arr, sizeof(int) * 3 * 5); for (size_t i = 0; i < 3; i++) { for (size_t j = 0; j < 5; j++) { printf("%d ", arr2[i][j]); } printf("\n"); } }
执行上述代码后,原本预期复制成功,却出现了如下段错误:
0 1 1 0 1 1 1 1 1 1 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 Segmentation fault
问题原因
核心问题是栈上二维数组和堆上指针数组的内存布局完全不同,直接用memcpy批量复制会彻底破坏指针数组的结构:
arr是栈上的二维数组,内存是连续的整块区域,15个int按行依次排列,没有额外的指针存储。arr2是指针数组:先分配了3个int*的空间用来存储行指针,每个指针又指向堆上独立的5个int空间。也就是说arr2本身只存储3个指针,真正的数据分散在堆的不同位置。
执行memcpy(arr2, arr, sizeof(int)*3*5)时:
- 首先会把
arr里的前几个int值覆盖arr2的指针区域(比如64位系统中,3个指针占24字节,对应6个int),把原本指向有效堆内存的指针改成了arr里的0、1这类无效地址,变成野指针。 - 其次,
arr2本身只分配了3个指针的空间(24字节),但你要复制60字节(15*4),属于越界写入,会破坏堆内存的管理结构。
后续通过arr2[i][j]访问时,本质是用被篡改的野指针去寻址,直接触发段错误。
正确的复制方式
应该逐行复制,针对每个行指针指向的内存单独拷贝:
for (int i = 0; i < row; i++) { memcpy(arr2[i], arr[i], sizeof(int) * col); }
这样既不会破坏arr2的指针结构,也能正确把arr的每一行数据复制到对应堆内存中。
内容的提问来源于stack exchange,提问作者eezhijun
相关产品推荐
相关产品推荐

