连续两次调用realloc函数失效求助:员工ID获取程序异常退出
连续调用realloc导致C程序异常的原因分析及修复
问题描述
编写了一段用于获取三位员工ID的C语言代码,连续两次调用realloc函数时程序出现异常,仅调用一次realloc时可正常运行。程序在完成首次输入后便直接退出,无法继续执行后续操作。
原代码
#include <stdio.h> #include <stdlib.h> char *ptr; int n; int main() { ptr = (char *)calloc(n, sizeof(char)); // First ID printf("Enter the length of your employ ID\n"); scanf("%d", &n); for (int i = 0; i <= n; i++) { scanf("%c", &ptr[i]); } for (int i = 0; i <= n; i++) { printf("%c", ptr[i]); } // Second ID printf("Enter the size of new ID\n"); scanf("%d", &n); ptr = (char *)realloc(ptr, n * sizeof(char)); for (int i = 0; i <= n; i++) { scanf("%c", &ptr[i]); } for (int i = 0; i <= n; i++) { printf("%c", ptr[i]); } // Third ID printf("Enter the size of new ID\n"); scanf("%d", &n); ptr = (char *)realloc(ptr, n * sizeof(char)); for (int i =0; i <=n; i++) { scanf("%c", &ptr[i]); } for (int i = 0; i <= n; i++) { printf("%c", ptr[i]); } return 0; }
核心错误原因
全局变量未初始化就使用
全局变量n默认初始值为0,调用calloc(n, sizeof(char))会分配0字节内存(返回NULL或空指针),后续写入ptr[i]直接触发内存越界,破坏堆结构,为后续realloc崩溃埋下隐患。scanf读取整数后残留换行符
使用scanf("%d", &n)读取整数时,输入缓冲区会留下用户按下的换行符\n,后续的scanf("%c", &ptr[i])会直接读取这个换行符,导致输入逻辑混乱,程序看似"提前退出"。数组越界访问
循环条件i <= n错误:如果ID长度为n,数组有效下标应为0到n-1(若存储字符串还需额外1字节存结束符)。当前代码分配n字节内存,却访问到ptr[n],直接越界破坏堆内存,导致realloc操作时堆结构异常,触发程序崩溃。realloc的不安全使用
直接将realloc的返回值赋值给原指针ptr,若realloc失败返回NULL,会丢失原指针地址,造成内存泄漏;但此处主要崩溃原因是堆已被前面的越界操作损坏,realloc无法正常执行。
修复后的代码
#include <stdio.h> #include <stdlib.h> int main() { char *ptr = NULL; int n; int c; // First ID printf("Enter the length of your employee ID: "); scanf("%d", &n); // 清理输入缓冲区的换行符 while ((c = getchar()) != '\n' && c != EOF); // 分配内存,额外1字节存字符串结束符 ptr = malloc((n + 1) * sizeof(char)); if (ptr == NULL) { fprintf(stderr, "Memory allocation failed\n"); return 1; } printf("Enter the ID: "); for (int i = 0; i < n; i++) { scanf("%c", &ptr[i]); } ptr[n] = '\0'; // 添加字符串结束符 printf("Your ID: %s\n", ptr); // Second ID printf("\nEnter the size of new ID: "); scanf("%d", &n); while ((c = getchar()) != '\n' && c != EOF); char *temp_ptr = realloc(ptr, (n + 1) * sizeof(char)); if (temp_ptr == NULL) { fprintf(stderr, "Reallocation failed\n"); free(ptr); return 1; } ptr = temp_ptr; printf("Enter the new ID: "); for (int i = 0; i < n; i++) { scanf("%c", &ptr[i]); } ptr[n] = '\0'; printf("Your new ID: %s\n", ptr); // Third ID printf("\nEnter the size of third ID: "); scanf("%d", &n); while ((c = getchar()) != '\n' && c != EOF); temp_ptr = realloc(ptr, (n + 1) * sizeof(char)); if (temp_ptr == NULL) { fprintf(stderr, "Reallocation failed\n"); free(ptr); return 1; } ptr = temp_ptr; printf("Enter the third ID: "); for (int i = 0; i < n; i++) { scanf("%c", &ptr[i]); } ptr[n] = '\0'; printf("Your third ID: %s\n", ptr); free(ptr); return 0; }
修复说明
- 改用局部变量替代全局变量,避免未初始化的问题
- 先读取ID长度再分配内存,保证内存大小符合需求
- 每次读取整数后清理输入缓冲区的换行符,避免干扰后续字符读取
- 分配内存时额外预留1字节用于存储字符串结束符
\0,修正循环条件为i < n,避免越界 - 使用临时变量接收
realloc的返回值,避免内存泄漏 - 添加内存分配失败的错误处理,增强程序健壮性
- 最后释放分配的内存,避免内存泄漏
内容的提问来源于stack exchange,提问作者Papayc
相关产品推荐
相关产品推荐

