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

C语言向函数传动态数组并realloc内存时出现段错误,求分析

问题分析与修复

核心错误:非法内存访问引发段错误

你的代码出现段错误的根源在于while (scanf("%d",znamky[*count])==1)这一行。znamky是int**类型(指向动态数组指针的指针),znamky[*count]等价于*(znamky + *count),这是在访问指针数组的第*count个元素,而非你要存储数字的动态数组元素地址。当*count大于0时,这个地址是完全随机的,往该地址写入数据会直接触发非法内存访问。

正确的写法应该是&(*znamky)[*count]或者*znamky + *count:

  • *znamky是main函数中动态分配的数组首指针(int*类型)
  • (*znamky)[*count]代表数组的第*count个元素,取其地址传给scanf,才能将读取的数字存入正确位置。

其他需要修正的问题

  1. realloc内存计算冗余:n * sizeof(int) +4完全多余,直接使用n * sizeof(int)即可——n是要分配的元素个数,每个元素占sizeof(int)字节,额外加4会造成内存浪费,甚至可能引发后续越界问题。
  2. 未检查realloc返回值:realloc可能分配失败并返回NULL,若直接将NULL赋值给*znamky,会丢失原有内存地址造成泄漏。需用临时变量接收返回值,确认成功后再更新指针。
  3. main函数中malloc失败后的冗余操作:malloc返回NULL时,free(NULL)合法但毫无必要,直接退出即可。
  4. 字符变量的冗余定义:你定义的overeni[2]、carka[2]等字符数组完全可以简化为单个字符变量,减少不必要的内存占用。

修正后的代码

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

int readInput(int **znamky, int *count)
{
    size_t n = 1;
    char overeni; 
    char znaminko;
    const char zavorka = '{';
    const char carka = ',';
    const char zavorka2 = '}';

    printf("Pocty bodu:\n");
    // 读取第一个字符并跳过前置空白
    if (scanf(" %c", &overeni) != 1 || overeni != zavorka)
    {
        printf("Nespravny vstup.\n");
        return EXIT_FAILURE;
    }

    while (1)
    {
        // 读取数字到数组当前位置
        if (scanf("%d", &(*znamky)[*count]) != 1)
        {
            printf("Nespravny vstup.\n");
            return EXIT_FAILURE;
        }

        // 读取数字后的分隔符或结束符
        if (scanf(" %c", &znaminko) != 1)
        {
            printf("Nespravny vstup.\n");
            return EXIT_FAILURE;
        }

        if (znaminko == carka)
        {
            *count += 1;
            // 检查是否需要扩容
            if (*count == n)
            {
                n *= 2;
                int *temp = realloc(*znamky, n * sizeof(int));
                if (temp == NULL)
                {
                    printf("Chyba alokace pameti.\n");
                    return EXIT_FAILURE;
                }
                *znamky = temp;
            }
        }
        else if (znaminko == zavorka2)
        {
            *count += 1;
            printf("utikam\n");
            return EXIT_SUCCESS;
        }
        else
        {
            printf("Nespravny vstup.\n");
            return EXIT_FAILURE;
        }
    }
}

int main(void)
{
    int *znamky = malloc(sizeof(int));
    int count = 0;

    if (znamky == NULL)
    {
        printf("Chyba alokace pameti.\n");
        return EXIT_FAILURE;
    }

    int result = readInput(&znamky, &count);
    
    // 测试:打印读取到的数字
    printf("Nacteno %d cisel:\n", count);
    for (int i = 0; i < count; i++)
    {
        printf("%d ", znamky[i]);
    }
    printf("\n");

    free(znamky);
    return result;
}

指针与数组传递的关键解释

  1. 为什么要用int **znamky?
    函数内部需要修改main函数中znamky指针的指向(realloc会返回新的内存地址)。如果只传递int *znamky,函数会得到指针的副本,修改副本不会影响main里的原指针。而传递int **znamky(指针的指针),函数可以通过*znamky直接修改main中的指针变量。

  2. 动态数组的正确访问方式

    • *znamky是动态数组的首地址(int*类型),用法和普通数组的首指针完全一致。
    • (*znamky)[i]等价于*( *znamky + i ),表示数组的第i个元素。
    • 给scanf传参时,需要传递元素的地址,所以用&(*znamky)[i]或者*znamky + i。

内容的提问来源于stack exchange,提问作者Matouš Kovář

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 23:10:13