C语言结构体指针数组填充代码崩溃,求问题排查与修正
问题分析:结构体指针数组填充时的运行崩溃问题
我来帮你拆解下代码里导致崩溃的几个关键问题:
参数传递错误,修改的是局部变量而非原数组
你在fuellen函数里写了spr=calloc(n,sizeof(springer));,但这里的spr是函数的形参,是主函数中spr数组的副本。修改这个局部指针完全不会影响主函数里的原数组,而且主函数里已经定义了springer *spr[N];——这是一个栈上的指针数组,本身不需要再用calloc分配内存,这一步相当于画蛇添足,还让局部的spr指向了堆内存,和原数组彻底脱节。指针数组元素未指向有效结构体内存
主函数里的spr[N]是一堆未初始化的野指针,你直接在函数里操作spr[i]->weiten或者(*spr[i]).name,本质是在访问野指针指向的内存,这必然会触发崩溃。正确的做法是给每个spr[i]单独分配springer结构体的内存。内存分配的大小错误(次要但值得注意)
就算你真的需要动态分配指针数组,calloc(n,sizeof(springer))也不对——因为spr是springer*类型的数组,每个元素是指针,应该分配sizeof(springer*)的大小,而不是整个结构体的大小。不过这个问题在修正前两个问题后就不存在了,因为主函数已经定义了固定大小的指针数组。
修正后的代码示例
填充函数与结构体定义
#include <stdlib.h> #include <string.h> #include <time.h> // 实现生成6-9之间随机数的函数 double zufallsWeite() { // 生成0-3的整数,加上6.0得到6.0-9.0的随机数 return (rand() % 4) + 6.0; } typedef struct { char* name; double weiten[3]; } springer; void fuellen(springer *spr[], const char* namen[], int n){ for(int i=0; i<n; i++){ // 为每个指针分配结构体内存 spr[i] = calloc(1, sizeof(springer)); // 分配name的内存(长度+1是为了存储字符串结束符'\0') spr[i]->name = calloc(strlen(namen[i]) + 1, sizeof(char)); // 复制名称字符串 strcpy(spr[i]->name, namen[i]); // 填充随机距离 spr[i]->weiten[0] = zufallsWeite(); spr[i]->weiten[1] = zufallsWeite(); spr[i]->weiten[2] = zufallsWeite(); } }
主函数调用
#include <stdio.h> #include <stdlib.h> int main() { const int N = 5; const char *names[] = { "Tom Mueller", "Timo Meier", "Ulf Sommer", "Tobi Winter", "Uwe Schmidt" }; springer *spr[N]; // 栈上的指针数组,每个元素是springer*类型 // 初始化随机数种子,确保每次运行得到不同的随机数 srand(time(NULL)); fuellen(spr, names, N); // 测试输出结果 for(int i=0; i<N; i++){ printf("Springer %d: Name=%s, Weiten=%.1f, %.1f, %.1f\n", i+1, spr[i]->name, spr[i]->weiten[0], spr[i]->weiten[1], spr[i]->weiten[2]); // 释放内存,避免泄漏:先释放name,再释放结构体 free(spr[i]->name); free(spr[i]); } return 0; }
额外注意事项
- 一定要初始化随机数种子:调用
srand(time(NULL)),否则zufallsWeite每次生成的随机数序列都会重复。 - 动态分配的内存必须释放:先释放结构体里的
name指针,再释放结构体本身,避免内存泄漏。 - 如果你的
zufallsWeite有其他实现逻辑,只需保证它返回6到9之间的double类型数值即可。
内容的提问来源于stack exchange,提问作者R. L.
相关产品推荐
相关产品推荐

