You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

连续两次调用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;
}

核心错误原因

  1. 全局变量未初始化就使用
    全局变量n默认初始值为0,调用calloc(n, sizeof(char))会分配0字节内存(返回NULL或空指针),后续写入ptr[i]直接触发内存越界,破坏堆结构,为后续realloc崩溃埋下隐患。

  2. scanf读取整数后残留换行符
    使用scanf("%d", &n)读取整数时,输入缓冲区会留下用户按下的换行符\n,后续的scanf("%c", &ptr[i])会直接读取这个换行符,导致输入逻辑混乱,程序看似"提前退出"。

  3. 数组越界访问
    循环条件i <= n错误:如果ID长度为n,数组有效下标应为0到n-1(若存储字符串还需额外1字节存结束符)。当前代码分配n字节内存,却访问到ptr[n],直接越界破坏堆内存,导致realloc操作时堆结构异常,触发程序崩溃。

  4. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 04:16:06