内存重分配后触发Access violation访问违例问题求助
访问违例(Access violation)错误排查与修复
错误原因分析
你的代码存在三个关键问题,直接或间接导致了Access violation错误:
1. 扩容时内存分配大小错误
redim函数中,realloc的第二个参数使用了sizeof(produs),但lista->v是produs**类型(指向produs指针的指针),正确的分配大小应该是sizeof(produs*)。原代码分配的内存远小于实际需求,导致后续访问数组元素时越界,触发访问违例。
2. 扩容函数传参类型不匹配
adauga函数中调用redim(&lista),传递的是Lista**类型指针,但redim的参数定义是Lista*,类型不匹配会导致函数内部错误修改不属于原列表的内存区域,破坏列表结构。
3. 浅拷贝导致的潜在内存问题
crearePr返回的produs结构体包含动态分配的字符串指针,直接通过*lista->v[lista->lungime] = p赋值属于浅拷贝,会导致多个结构体实例共享同一块字符串内存,后续释放时会引发双重释放错误。
修复后的完整代码
#include <string.h> #include <stdio.h> #include <stdlib.h> typedef struct { char* denumire, * producator; int cantitate; }produs; typedef struct { produs** v; int lungime; int capacitate; } Lista; // 创建produs实例,返回动态分配的结构体指针 produs* crearePr(char* nume, char* producator, int cantitate) { produs* material = (produs*)malloc(sizeof(produs)); material->denumire = (char*)malloc(strlen(nume) + 1); strcpy(material->denumire, nume); material->producator = (char*)malloc(strlen(producator) + 1); strcpy(material->producator, producator); material->cantitate = cantitate; return material; } void creareLi(Lista* lista) { lista->lungime = 0; lista->capacitate = 1; lista->v = (produs**)malloc(sizeof(produs*) * lista->capacitate); } void redim(Lista *l) { l->capacitate *= 2; // 修复:分配produs*的大小,而非produs的大小 produs** temp = (produs**)realloc(l->v, sizeof(produs*) * l->capacitate); // 检查realloc是否成功 if (temp != NULL) { l->v = temp; } else { printf("扩容失败\n"); exit(1); } } void adauga(Lista *lista, produs* p) { if (lista->lungime == lista->capacitate) { // 修复:传递正确的Lista*类型参数 redim(lista); } // 直接存储crearePr返回的指针,无需重复分配produs内存 lista->v[lista->lungime] = p; lista->lungime++; } // 新增:释放列表所有动态分配的内存,避免内存泄漏 void elibereazaLista(Lista* lista) { for (int i = 0; i < lista->lungime; i++) { free(lista->v[i]->denumire); free(lista->v[i]->producator); free(lista->v[i]); } free(lista->v); lista->lungime = 0; lista->capacitate = 0; } int main() { Lista lista; creareLi(&lista); adauga(&lista, crearePr("Zahar", "Tarom", 100)); // 测试输出验证功能 printf("Denumire: %s\n", lista.v[0]->denumire); printf("Producator: %s\n", lista.v[0]->producator); printf("Cantitate: %d\n", lista.v[0]->cantitate); // 释放内存 elibereazaLista(&lista); return 0; }
修复说明
- 修正扩容内存大小:
redim中使用sizeof(produs*)计算分配内存,确保每个数组元素都是合法的produs指针。 - 修正传参类型:
adauga中调用redim(lista),传递正确的Lista*类型参数,保证函数操作的是原列表的内存区域。 - 解决浅拷贝问题:将
crearePr改为返回produs*指针,直接存入列表避免重复分配;新增elibereazaLista函数,确保所有动态分配的内存都被正确释放,避免内存泄漏和双重释放问题。
内容的提问来源于stack exchange,提问作者Eduard Şubredu
相关产品推荐
相关产品推荐

