c - 重新分配中的双重释放或损坏(出)

标签 c dynamic-memory-allocation sizeof post-increment

几天来我一直在尝试解决代码中的问题,但我仍然坚持不懈。 我想通过 realloc 在选项卡中插入一个值,但出现内存泄漏(或其他问题),而且我不知道为什么。

这是我的代码:

#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>

typedef struct struct_vector{
    int nbElement;
    double* element;
}s_vector;

typedef s_vector* p_s_vector;

p_s_vector vector_alloc(size_t n){
    p_s_vector vect =(p_s_vector) malloc(sizeof(p_s_vector));
    vect->nbElement = n;
    vect->element = (double*) malloc(sizeof(double) * n);
    for(int i=0; i<n; i++){
        vect->element[i] = i; 
    }
    return vect;
}

void vector_free(p_s_vector p_vector){
    free(p_vector->element);
    free(p_vector);
    p_vector = NULL;
}

void vector_insert(p_s_vector p_vector, size_t i, double v){
    if(i < 0 || i > p_vector->nbElement)
        exit(0);
    else{   
        p_s_vector temp = vector_alloc(p_vector->nbElement);
        for(int k=0; k < temp->nbElement; k++)
            temp->element[k] = p_vector->element[k];
            
        p_vector->element = (double*)realloc(p_vector->element,sizeof(double)*(p_vector->nbElement++));
        for(int k=0; k<i; k++)
            p_vector->element[k] = temp->element[k];
            
        p_vector->element[i] = v;
        for(int k=i+1; k<p_vector->nbElement; k++)
            p_vector->element[k] = temp->element[k-1];
            
        vector_free(temp);
    }
}

int main(){
    p_s_vector vect = vector_alloc(3);
    
    vector_insert(vect, 1, 11);
    
    for(int i=0; i<vect->nbElement; i++){
        printf("%.1f\n",vect->element[i]);
    }
    
    vector_free(vect);
    return 0;
}

当我运行程序时,出现双重释放或损坏(输出)错误。 使用 Valgrind 命令,我有很多“地址 0x4a4d048 在大小为 8 的 block 分配后是 0 字节”,我不明白为什么

如果有人能帮助我,那就太好了。 谢谢。

最佳答案

您的代码中有两个错误。线路

    p_s_vector vect = (p_s_vector) malloc(sizeof(p_s_vector));

应该是

    p_s_vector vect = malloc(sizeof(s_vector));

因为您想要分配一个结构而不是指向它的指针(并且不转换malloc的返回值)。此外,您还应该在重新分配中预先增加计数,因此

    p_vector->element = (double *)realloc(p_vector->element, sizeof(double) * (p_vector->nbElement++));

应该是

    p_vector->element = realloc(p_vector->element, sizeof(double) * (++p_vector->nbElement));

最好避免表达式中的副作用,因此我建议在单独的语句中增加计数。

为了简化内存分配并使其不易出错,我建议定义如下宏函数:

#include <errno.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define NEW_ARRAY(pointer, length) \
    { \
        (pointer) = malloc(((size_t) length) * sizeof (pointer)[0]); \
        if ((pointer) == NULL) { \
            fprintf(stderr, "Allocating %lu bytes of memory with malloc failed: %s\n", ((long unsigned int) length) * sizeof (pointer)[0], strerror(errno)); \
            exit(EXIT_FAILURE); \
        } \
    }

#define RENEW_ARRAY(pointer, length) \
    { \
        (pointer) = realloc((pointer), ((size_t) length) * sizeof (pointer)[0]); \
        if ((pointer) == NULL) { \
            fprintf(stderr, "Allocating %lu bytes of memory with realloc failed: %s\n", ((long unsigned int) length) * sizeof (pointer)[0], strerror(errno)); \
            exit(EXIT_FAILURE); \
        } \
    }

#define NEW(pointer) NEW_ARRAY((pointer), 1)

typedef struct struct_vector {
    int nbElement;
    double *element;
} s_vector;

typedef s_vector *p_s_vector;

p_s_vector vector_alloc(size_t n)
{
    p_s_vector vect;
    NEW(vect);
    vect->nbElement = n;
    NEW_ARRAY(vect->element, n);
    for (int i = 0; i < n; i++) {
        vect->element[i] = i;
    }
    return vect;
}

void vector_free(p_s_vector p_vector)
{
    free(p_vector->element);
    free(p_vector);
    p_vector = NULL;
}

void vector_insert(p_s_vector p_vector, size_t i, double v)
{
    if (i < 0 || i > p_vector->nbElement) {
        exit(0);
    } else {
        p_s_vector temp = vector_alloc(p_vector->nbElement);
        for (int k = 0; k < temp->nbElement; k++) {
            temp->element[k] = p_vector->element[k];
        }

        p_vector->nbElement++;
        RENEW_ARRAY(p_vector->element, p_vector->nbElement);

        for (int k = 0; k < i; k++) {
            p_vector->element[k] = temp->element[k];
        }

        p_vector->element[i] = v;
        for (int k = i + 1; k < p_vector->nbElement; k++) {
            p_vector->element[k] = temp->element[k - 1];
        }

        vector_free(temp);
    }
}

int main()
{
    p_s_vector vect = vector_alloc(3);

    vector_insert(vect, 1, 11);

    for (int i = 0; i < vect->nbElement; i++) {
        printf("%.1f\n", vect->element[i]);
    }

    vector_free(vect);
    return 0;
}

最后,如果您删除“p”和“s”前缀,您的代码会变得不那么嘈杂;我将 vector 数据类型简单地定义为

struct VectorDesc {
    int nbElement;
    double *element;
};

typedef struct VectorDesc *Vector;

关于c - 重新分配中的双重释放或损坏(出),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70996690/

相关文章:

c - 嵌套for循环的解释

有人可以解释这个 OpenCL 程序有什么问题吗?

c - 实现用户级线程库启动一个新线程[作业]

将内联汇编从 Intel 语法转换为 AT&T 语法

c - 为什么编码器将结构指针的值分配给静态结构?

c - fgets() 与 realloc() 的奇怪行为

C sizeof 字符指针

c - 使用结构体和多线程时出现 malloc.c 错误

c - 如何使用 sizeof 运算符计算出使用多少字节来存储 C 中的变量?

char 指针作为函数参数