C语言结构体内部数组元素赋值失败问题排查求助
矩阵初始化后打印全0的问题排查与解决
问题概述
需要创建MAT_COUNT个matList结构体,每个结构体的matrix数组需正确初始化,预期打印结果为:
1.100000 2.100000 3.200000 4.200000
但实际输出全为0:
0.000000 0.000000 0.000000 0.000000
通过GDB调试时,在赋值语句执行过程中打印m[i][j]显示为0,怀疑赋值操作失败。
原代码
#include<stdio.h> #include<stdlib.h> #define MAT_SIZE 2 #define MAT_COUNT 3 typedef double mat[MAT_SIZE][MAT_SIZE]; typedef struct matList{ const char *name; mat matrix; }matList; void init_mat(mat m) { for(int i = 0; i < MAT_SIZE; i++){ for(int j = 0; j < MAT_SIZE; j++){ m[i][j] = i * 2.1 + (double) j + 1.1; printf("(i,j)=%f\n",m[i][j]); } } } //allocate matList. matList *create_mat(const char *name) { matList *tempMat = malloc(sizeof *tempMat); if(tempMat != NULL) { tempMat->name = name; init_mat(tempMat->matrix); } return tempMat; } // freematList void free_matList(matList **mats) { if(mats){ for(int i = 0; i < MAT_COUNT; i++){ free(mats[i]); } } } // return non zero if successful int allocate_matList(matList **mats) { if(mats){ mats[0] = create_mat("MAT_A"); mats[1] = create_mat("MAT_B"); mats[2] = create_mat("MAT_C"); if(mats[0] && mats[1] && mats[2]) return 1; } } int main(void) { matList *mats[MAT_COUNT]; if(allocate_matList(mats)){ printf("mat[2] name: %s\n",mats[2]->name); size_t row = sizeof(mats[2]->matrix) / sizeof (mats[2]->matrix[0]); size_t col = sizeof(mats[2]->matrix[0]) / sizeof(mats[2]->matrix[0][0]); printf("row: %ld col: %ld\n",row,col); for(size_t i = 0; i < row; i++){ for(size_t j = 0; j < col; j++){ printf("%f\t",mats[2]->matrix[row][col]); } printf("\n"); } } free_matList(mats); exit(EXIT_SUCCESS); }
GDB调试信息
(gdb) break 23 Breakpoint 1 at 0x11d9: file array_struct170.c, line 23. (gdb) s The program is not being run. (gdb) run Starting program: /home/jian/helloc/a.out [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". Breakpoint 1, init_mat (m=0x5555555592a8) at array_struct170.c:23 23 for(int i = 0; i < MAT_SIZE; i++){ (gdb) s 24 for(int j = 0; j < MAT_SIZE; j++){ (gdb) s 25 m[i][j] = i * 2.1 + (double) j + 1.1; (gdb) print m[i][j] $1 = 0
问题根源与解决方法
1. 打印循环的索引越界错误
main函数的打印循环中,错误地使用row和col作为数组索引:
printf("%f\t",mats[2]->matrix[row][col]);
由于MAT_SIZE=2,row和col的值均为2,而矩阵的有效索引范围是0~1,这会访问到矩阵数组的越界内存,该区域未被初始化,因此输出全0。
修正:使用循环变量i和j作为索引:
printf("%f\t",mats[2]->matrix[i][j]);
2. GDB调试的时机问题
在GDB中执行到赋值语句m[i][j] = ...时立即打印m[i][j],此时赋值操作尚未完成(代码行25还未执行结束),所以显示的是赋值前的初始值0。继续执行一步(输入s命令)后再打印,就能看到正确的赋值结果。
3. allocate_matList函数的返回值缺失
当mats为空或者任意一个create_mat调用失败时,函数没有明确返回值,会触发未定义行为。
修正:在函数末尾补充返回值:
return 0;
修正后的代码
#include<stdio.h> #include<stdlib.h> #define MAT_SIZE 2 #define MAT_COUNT 3 typedef double mat[MAT_SIZE][MAT_SIZE]; typedef struct matList{ const char *name; mat matrix; }matList; void init_mat(mat m) { for(int i = 0; i < MAT_SIZE; i++){ for(int j = 0; j < MAT_SIZE; j++){ m[i][j] = i * 2.1 + (double) j + 1.1; printf("(i,j)=%f\n",m[i][j]); } } } //allocate matList. matList *create_mat(const char *name) { matList *tempMat = malloc(sizeof *tempMat); if(tempMat != NULL) { tempMat->name = name; init_mat(tempMat->matrix); } return tempMat; } // freematList void free_matList(matList **mats) { if(mats){ for(int i = 0; i < MAT_COUNT; i++){ free(mats[i]); } } } // return non zero if successful int allocate_matList(matList **mats) { if(mats){ mats[0] = create_mat("MAT_A"); mats[1] = create_mat("MAT_B"); mats[2] = create_mat("MAT_C"); if(mats[0] && mats[1] && mats[2]) return 1; } return 0; // 补充缺失的返回值 } int main(void) { matList *mats[MAT_COUNT]; if(allocate_matList(mats)){ printf("mat[2] name: %s\n",mats[2]->name); size_t row = sizeof(mats[2]->matrix) / sizeof (mats[2]->matrix[0]); size_t col = sizeof(mats[2]->matrix[0]) / sizeof(mats[2]->matrix[0][0]); printf("row: %ld col: %ld\n",row,col); for(size_t i = 0; i < row; i++){ for(size_t j = 0; j < col; j++){ printf("%f\t",mats[2]->matrix[i][j]); // 使用i,j作为索引 } printf("\n"); } } free_matList(mats); exit(EXIT_SUCCESS); }
内容的提问来源于stack exchange,提问作者jian
相关产品推荐
相关产品推荐

