You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

内存重分配后触发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;
}

修复说明

  1. 修正扩容内存大小:redim中使用sizeof(produs*)计算分配内存,确保每个数组元素都是合法的produs指针。
  2. 修正传参类型:adauga中调用redim(lista),传递正确的Lista*类型参数,保证函数操作的是原列表的内存区域。
  3. 解决浅拷贝问题:将crearePr改为返回produs*指针,直接存入列表避免重复分配;新增elibereazaLista函数,确保所有动态分配的内存都被正确释放,避免内存泄漏和双重释放问题。

内容的提问来源于stack exchange,提问作者Eduard Şubredu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 04:51:27