调用初始化函数导致fprintf输出异常的技术问询
代码中的fprintf(output_filep, "testing opening output, success\n");语句,只要不调用最后if-else块内的三个初始化函数,就能正常将消息写入输出文件;但如果注释掉该if-else块,程序可运行却无内容输出。疑问:为何调用print语句之后的函数会导致前置fprintf失效?
已尝试操作:注释最后三个if-else语句,也尝试过在main函数前后定义这些函数,观察到只要不调用这些函数,fprintf语句就能正常工作。
相关代码片段
while(output_read == false) { ... fscanf(input_filep, "%s", &output_file); output_filep = fopen(output_file, "w"); if(output_filep != NULL) { output_read = true; } else { fprintf(stderr, "ERROR: output file name not in file"); input_filep = NULL; free(input_filep); free(output_filep); return 1; } } fprintf(output_filep, "testing opening output, success\n"); int i; int **boardpp; // 注意:此处存在关键错误 boardpp = (int**)malloc(sizeof(int) * num_rows); if(boardpp == NULL) { fprintf(stderr, "ERROR: Array of pointers for 2-D array could not be allocated\n"); fprintf(output_filep, "ERROR: Array of pointers for 2-D array could not be allocated\n"); free(boardpp); return 1; } for(i = 0; i < num_rows; i++) { boardpp[i] = (int*)malloc(sizeof(int) * num_cols); if(boardpp[i] == NULL) { fprintf(stderr, "ERROR: Array storage could not be allocated\n"); fprintf(output_filep, "ERROR: Array storage could not be allocated\n"); free(boardpp[i]); return 1; } } // 此代码块导致输出文件打印异常 if(init_type == 1) { InitBoardRand(boardpp, num_rows, num_cols, initSeed); } else if(init_type == 2) { InitBoardChecker(boardpp, num_rows, num_cols); } else if(init_type == 3) { InitBoardAllWhite(boardpp, num_rows, num_cols); }
问题分析与解决思路
核心错误:二维数组内存分配类型不匹配
你分配指针数组时用了malloc(sizeof(int) * num_rows),但boardpp是int**类型,每个元素是int*指针,正确写法应为malloc(sizeof(int*) * num_rows)。如果指针大小大于int(比如64位系统下指针占8字节、int占4字节),会导致分配的内存不足,后续初始化函数操作boardpp时出现内存越界,直接破坏output_filep的内部结构,导致之前的输出内容丢失。这是最可能的原因,优先修正这个错误。文件缓冲区未主动刷新
C标准库对文件IO默认是全缓冲模式,只有缓冲区满或程序正常退出时才会把内容写入磁盘。如果初始化函数导致程序异常崩溃,缓冲区里的fprintf内容还没来得及写入文件,就会看起来像是输出失效。可以在fprintf之后加上fflush(output_filep);强制刷新缓冲区,验证是否是这个问题。排查初始化函数的内存操作
检查三个初始化函数的代码,看是否存在数组越界、野指针等非法内存访问,这类操作可能会破坏程序的其他数据结构(包括文件流指针)。确认程序是否提前退出
检查初始化函数内部有没有隐性的return或exit调用,导致程序在输出内容写入文件前就提前终止。
内容的提问来源于stack exchange,提问作者ssz6

