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,才能将读取的数字存入正确位置。
其他需要修正的问题
- realloc内存计算冗余:
n * sizeof(int) +4完全多余,直接使用n * sizeof(int)即可——n是要分配的元素个数,每个元素占sizeof(int)字节,额外加4会造成内存浪费,甚至可能引发后续越界问题。 - 未检查realloc返回值:realloc可能分配失败并返回NULL,若直接将NULL赋值给
*znamky,会丢失原有内存地址造成泄漏。需用临时变量接收返回值,确认成功后再更新指针。 - main函数中malloc失败后的冗余操作:malloc返回NULL时,
free(NULL)合法但毫无必要,直接退出即可。 - 字符变量的冗余定义:你定义的
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; }
指针与数组传递的关键解释
为什么要用
int **znamky?
函数内部需要修改main函数中znamky指针的指向(realloc会返回新的内存地址)。如果只传递int *znamky,函数会得到指针的副本,修改副本不会影响main里的原指针。而传递int **znamky(指针的指针),函数可以通过*znamky直接修改main中的指针变量。动态数组的正确访问方式
*znamky是动态数组的首地址(int*类型),用法和普通数组的首指针完全一致。(*znamky)[i]等价于*( *znamky + i ),表示数组的第i个元素。- 给scanf传参时,需要传递元素的地址,所以用
&(*znamky)[i]或者*znamky + i。
内容的提问来源于stack exchange,提问作者Matouš Kovář
相关产品推荐
相关产品推荐

