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

realloc扩容失败求助:向素数数组添加元素时内存分配出错

分析realloc调用失败及代码中的关键问题

核心错误原因

1. 初始内存分配大小错误

main函数里int *primes = (int *)(malloc(1));只分配了1字节,但int类型在大多数系统中占4字节,这直接导致*primes = 2;操作越界写入,破坏堆内存结构,后续的realloc调用会因为堆损坏而失败,返回NULL。

2. 指针传值调用导致修改无法同步

makePrimes函数的第一个参数int *primes是值传递,函数内部对primes的修改(比如primes = realloc(...))只会改变函数内的局部指针,不会影响main函数中的primes指针。就算realloc成功,main里的指针还是指向原来的小内存块;如果realloc返回NULL,原来的内存地址会被覆盖,直接造成内存泄漏。

3. 找到素数后未完成赋值操作

在makePrimes中,找到素数后只执行了*(primes + (*primesLength - 1));,这行代码只是读取数组最后一个位置的值,并没有把找到的lastValue存入数组,等于白扩容了。

4. isPrime函数逻辑冗余(非直接崩溃原因,但影响效率)

isPrime里的循环for (int iii = 0; iii < (input - 2); iii++)完全没必要,只需要循环到sqrt(input)即可,当前写法会导致大数的素数判断效率极低。

修正后的代码

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

// 要修改main中的指针,需传递指针的指针
void makePrimes(int **primes, int *primesLength, int primeTarget);
int isPrime(int input);

int main(void)
{
    // 初始分配1个int的大小,而非1字节
    int *primes = malloc(sizeof(int));
    if (primes == NULL) {
        perror("malloc failed");
        return 1;
    }
    *primes = 2;
    int primesLength = 1;
    // 传递指针的地址
    makePrimes(&primes, &primesLength, 3);
    
    // 先判断长度,避免越界访问
    if (primesLength >= 3) {
        printf("%d\n", primes[2]);
    } else {
        printf("数组长度不足\n");
    }
    
    free(primes);
    return 0;
}

//* 找到目标序号的素数(2是第0个素数)
//! 注意:primeTarget从0开始计数,primesLength从1开始计数
void makePrimes(int **primes, int *primesLength, int primeTarget)
{
    if (*primesLength >= primeTarget + 1)
        return;

    int lastValue = (*primes)[*primesLength - 1];
    while (*primesLength != primeTarget + 1)
    {
        lastValue++;
        if (isPrime(lastValue))
        {
            (*primesLength)++;
            // 用临时变量接收realloc结果,避免失败时丢失原内存
            int *temp = realloc(*primes, *primesLength * sizeof(int));
            if (temp == NULL) {
                perror("realloc failed");
                // 错误回滚长度
                (*primesLength)--;
                return;
            }
            *primes = temp;
            // 将找到的素数存入数组末尾
            (*primes)[*primesLength - 1] = lastValue;
        }
    }
}

//* 判断一个整数是否为素数
int isPrime(int input)
{
    if (input <= 1)
        return 0;
    if (input == 2)
        return 1;
    // 偶数直接排除
    if (input % 2 == 0)
        return 0;
    // 只检查到平方根,且只遍历奇数
    for (int testFactor = 3; testFactor <= sqrt(input); testFactor += 2)
    {
        if (input % testFactor == 0)
            return 0;
    }
    return 1;
}

修正要点说明

  • 初始malloc改为malloc(sizeof(int)),分配正确的内存大小。
  • makePrimes的第一个参数改为int **primes(指针的指针),确保函数能修改main中的指针变量。
  • 使用临时变量接收realloc返回值,避免realloc失败时丢失原内存地址。
  • 找到素数后,将lastValue赋值给数组的新位置。
  • 优化isPrime函数,减少不必要的循环,提升效率。
  • 添加内存分配失败的错误处理,增强代码健壮性。

内容的提问来源于stack exchange,提问作者Jman4546

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 18:57:41