含指针成员的结构体指针的动态内存分配问题
解决结构体指针二维数组的内存分配与访问违规问题
我看了你的代码,出现“Access violation writing location”错误,主要是踩了几个动态内存分配和访问的典型坑,下面给你逐一拆解并修复:
核心错误点分析
1. 未为结构体实例分配内存
你只给person(结构体指针数组)分配了内存,但数组里的每个person[i]都是未初始化的野指针,直接去访问person[i]->name这类成员,相当于操作随机内存,必然触发访问违规。
2. malloc的大小计算错误
你写的:
person = (detailsOf **)malloc(maxSize * sizeof(detailsOf **));
这里sizeof(detailsOf **)是“指针的指针”的大小,而我们需要的是每个数组元素(detailsOf*类型)的大小,应该改成sizeof(detailsOf *)。
3. scanf参数传递错误
在inputValue函数里,读取birthdate和phoneNum的元素时,你传的是person[i]->birthdate[j](一个int值),但scanf需要的是内存地址,应该传&person[i]->birthdate[j](或者直接用person[i]->birthdate + j,因为数组名本身是指针)。
4. 内存释放逻辑错误
- 你试图循环释放
name[j]、phoneNum[j]这类单个元素,但这些都是calloc分配的连续数组内存,只需要直接释放对应的指针(比如free(person[i]->name))即可,循环释放单个元素会导致未定义行为。 - 释放顺序要注意:先释放结构体内部的成员指针,再释放结构体本身,最后释放结构体指针数组。
修正后的完整代码
#ifdef _MSC_VER #define _CRT_SECURE_NO_WARNINGS #endif #include <stdio.h> #include<string.h> #include <stdlib.h> typedef struct template{ char *name; int *birthdate; int *phoneNum; } detailsOf; void inputValue(detailsOf **person, int maxSize); int main() { detailsOf **person; int maxSize = 0; printf("Max:"); scanf("%d", &maxSize); // 第一步:分配结构体指针数组的内存 person = malloc(maxSize * sizeof(detailsOf *)); if (person == NULL) { printf("Failed to allocate array\n"); exit(EXIT_FAILURE); } // 第二步:为每个结构体实例分配内存,并初始化成员指针 for (int i = 0; i < maxSize; i++) { // 先给结构体本身分配内存 person[i] = malloc(sizeof(detailsOf)); if (person[i] == NULL) { printf("Failed to allocate struct\n"); exit(EXIT_FAILURE); } // 再给结构体的成员指针分配内存 person[i]->name = calloc(21, sizeof(char)); person[i]->birthdate = calloc(8, sizeof(int)); person[i]->phoneNum = calloc(16, sizeof(int)); } inputValue(person, maxSize); // 第三步:正确释放内存 for (int i = 0; i < maxSize; i++) { // 先释放结构体内部的成员指针 free(person[i]->name); free(person[i]->birthdate); free(person[i]->phoneNum); // 再释放结构体本身 free(person[i]); } // 最后释放结构体指针数组 free(person); return 0; } void inputValue(detailsOf **person, int maxSize) { for (int i = 0; i < maxSize; i++) { printf("Name of %d: ", i + 1); scanf("%s", person[i]->name); // name是char*,直接传指针即可 printf("Birthdate of %d (8 digits):\n", i + 1); for (int j = 0; j < 8; j++) { printf("Digit %d: ", j + 1); scanf("%d", &person[i]->birthdate[j]); // 传int变量的地址 } printf("Phone number of %d (16 digits):\n", i + 1); for (int k = 0; k < 16; k++) { printf("Digit %d: ", k + 1); scanf("%d", &person[i]->phoneNum[k]); // 传int变量的地址 } } printf("SUCCESS\n"); }
关键修复说明
- 分层分配内存:先分配结构体指针数组,再逐个分配结构体实例,最后分配结构体内部的成员指针,确保每一层指针都指向有效的内存。
- 修正scanf参数:读取int类型时必须传递变量的地址,否则
scanf无法修改变量的值,还会导致内存访问错误。 - 正确释放内存:按照“反向分配顺序”释放内存,避免出现悬空指针或重复释放的问题。
内容的提问来源于stack exchange,提问作者The Sheyx
相关产品推荐
相关产品推荐

