C语言结构体动态内存分配问题:同一工人无法分配多个项目的函数修复
C语言结构体动态内存分配问题:同一工人无法分配多个项目的函数修复
我来帮你看看这个问题哈,你的addWorkerToProject函数现在没法给同一个工人添加多个项目,核心是动态内存分配的逻辑出了几个关键问题,咱们一步步拆解修复:
先说说原代码里的几个明显问题
- 每次调用都覆盖了之前的项目数组指针:原代码里每次调用都直接给
worker->projects用malloc分配新内存,这会把之前存储的项目数组指针直接覆盖掉,之前加的项目自然就丢了,第二次调用肯定看不到第一个项目。 - 内存分配的大小完全错误:
malloc(sizeof (strlen(project)+1))这个写法完全不对,worker->projects是Project**类型的指针数组,每个元素是一个Project*指针,所以分配的大小应该是指针的大小 × 数组的长度,而不是字符串长度相关的数值。 - 结构体定义不完整:你的
struct Worker和struct Project定义缺少大括号和分号,而且没有typedef的话,每次声明变量都要写struct,不太方便。 - 没有正确处理新项目的存储:原代码里直接给
worker->projects[worker->projectCount]->name赋值,这里worker->projects[worker->projectCount]是个未初始化的指针,直接访问会导致野指针错误,要么直接存储传入的Project*指针(前提是这个项目对象不会被提前释放),要么为新的Project分配内存并拷贝数据。
修复后的完整代码示例
先把结构体定义补全,再修复addWorkerToProject函数:
// 先提前声明结构体,解决互相引用的问题 struct Project; typedef struct Worker { char *name; struct Project **projects; // 这里用struct Project**因为提前声明了 int projectCount; } Worker; typedef struct Project { char *name; Worker **workers; int workerCount; // 假设FeatureNode是已经定义好的结构体 struct FeatureNode *features; } Project; void addWorkerToProject(Worker *worker, Project *project) { // 1. 先扩容项目数组:如果是第一次添加,分配1个指针的空间;否则扩容为当前数量+1 Project **tempProjects = realloc(worker->projects, sizeof(Project*) * (worker->projectCount + 1)); if (tempProjects == NULL) { // 内存分配失败的处理,比如打印错误后返回 perror("Failed to realloc projects"); return; } worker->projects = tempProjects; // 2. 将传入的项目指针存入数组的新位置 // 这里直接存储project指针,前提是project对象的生命周期比worker长,不会提前被释放 worker->projects[worker->projectCount] = project; // 如果需要拷贝项目的name而不是共享指针,可以这样做(可选): // worker->projects[worker->projectCount] = malloc(sizeof(Project)); // if (worker->projects[worker->projectCount] == NULL) { // perror("Failed to malloc Project"); // return; // } // worker->projects[worker->projectCount]->name = strdup(project->name); // worker->projects[worker->projectCount]->workers = NULL; // worker->projects[worker->projectCount]->workerCount = 0; // worker->projects[worker->projectCount]->features = NULL; // 3. 项目计数加1 worker->projectCount++; }
关键修复点的解释
- 用
realloc扩容数组:realloc可以帮我们把原来的数组内存扩容到新的大小,同时保留原来的数据,这就解决了每次覆盖之前项目的问题。第一次调用时worker->projects是NULL,realloc会等价于malloc,分配新的内存。 - 正确计算内存大小:
sizeof(Project*) * (worker->projectCount + 1),这里sizeof(Project*)是单个项目指针的大小,乘以新的数组长度(当前数量+1),确保有足够的空间存新的项目指针。 - 内存分配失败的检查:一定要检查
realloc和malloc的返回值,如果是NULL说明内存分配失败,要做错误处理,避免程序崩溃。 - 正确存储项目指针:直接把传入的
project指针存入数组,这样就可以直接访问项目的name了。如果你不想共享原项目对象,而是要拷贝一份,可以用注释里的方式,用malloc分配新的Project结构体,再用strdup拷贝字符串(strdup内部会调用malloc和strcpy)。
测试示例的用法
比如你要给Sean添加两个项目,可以这样写:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> // 上面的结构体和函数定义放在这里 int main() { // 创建工人Sean Worker *sean = malloc(sizeof(Worker)); sean->name = strdup("Sean"); sean->projects = NULL; sean->projectCount = 0; // 创建两个项目 Project *firstProject = malloc(sizeof(Project)); firstProject->name = strdup("first"); firstProject->workers = NULL; firstProject->workerCount = 0; firstProject->features = NULL; Project *secondProject = malloc(sizeof(Project)); secondProject->name = strdup("second"); secondProject->workers = NULL; secondProject->workerCount = 0; secondProject->features = NULL; // 添加项目到Sean addWorkerToProject(sean, firstProject); addWorkerToProject(sean, secondProject); // 打印测试 for (int i = 0; i < sean->projectCount; i++) { printf("Sean's project %d: %s\n", i+1, sean->projects[i]->name); } // 记得释放内存,避免内存泄漏 free(sean->name); free(sean->projects); free(sean); free(firstProject->name); free(firstProject); free(secondProject->name); free(secondProject); return 0; }
运行这个程序,就能看到Sean的两个项目都被正确打印出来啦。
备注:内容来源于stack exchange,提问作者strtrs
相关产品推荐
相关产品推荐

