这个C代码会泄漏内存吗?

这个C代码会泄漏内存吗?,c,pointers,memory-management,memory-leaks,C,Pointers,Memory Management,Memory Leaks,这是我的代码: typedef struct { int x; int *t; }vector; vector fct (vector v){ vector w; int i; w.x=v.x; w.t=malloc(w.x *sizeof(int)); for (i=0; i<w.x; i++) w.t[i]=2*v.t[i]; return w; } int main (){ int i;

这是我的代码:

typedef struct {
    int x;
    int *t;
}vector;

vector fct (vector v){
    vector w;
    int i;
    w.x=v.x;
    w.t=malloc(w.x *sizeof(int));
    for (i=0; i<w.x; i++)
        w.t[i]=2*v.t[i];
    return w;
}


int main (){
    int i;
    vector v;
    v.x=2;
    v.t=malloc(2*sizeof(int));
    v.t[0]=1; v.t[1]=5;
    v=fct(v);
    for (i=0; i<2; i++)
        printf("%d \t",v.t[i]);
    puts("");
    free(v.t);
    return 0;
}
typedef结构{
int x;
int*t;
}载体;
向量fct(向量v){
向量w;
int i;
w、 x=v.x;
w、 t=malloc(w.x*sizeof(int));

对于(i=0;i确定。向量t分配两次,释放一次。整个体系结构看起来有问题。

确定。向量t分配两次,释放一次。整个体系结构看起来有问题

v.t=malloc(2*sizeof(int));
在这里,您将分配的内存分配给
v.t

v=fct(v);
然后在这里用从
fct
返回的内容覆盖
v
的所有字段。这将丢弃
v.t
的旧值,导致内存泄漏

main
末尾对
free
的调用正在释放
fct
内部分配的内存

您可以通过保存
v.t
并在保存的指针上调用
free
来修复此漏洞:

vector v;
int *vt_sav;
v.x=2;
v.t=malloc(2*sizeof(int));
vt_sav = v.t;
v.t[0]=1; v.t[1]=5;
v=fct(v);
free(vt_sav);
在这里,您将分配的内存分配给
v.t

v=fct(v);
然后在这里用从
fct
返回的内容覆盖
v
的所有字段。这将丢弃
v.t
的旧值,导致内存泄漏

main
末尾对
free
的调用正在释放
fct
内部分配的内存

您可以通过保存
v.t
并在保存的指针上调用
free
来修复此漏洞:

vector v;
int *vt_sav;
v.x=2;
v.t=malloc(2*sizeof(int));
vt_sav = v.t;
v.t[0]=1; v.t[1]=5;
v=fct(v);
free(vt_sav);

是的,您正在泄漏内存。w.t永远不会释放。
还可以通过指针而不是值传递结构。返回向量也很昂贵

您的新程序可以如下所示:

#include <stdio.h>


typedef struct {
    int x;
    int *t;
}vector;

void fct (vector *v, vector * w){

    int i;

    w->x = v->x;

    for (i=0; i<w->x; i++)
        w->t[i]=2*v->t[i];
}


int main (){
    int i;
    vector v;
    vector w;

    v.x=2;

    v.t = malloc(2*sizeof(int));
    w.t = malloc(2*sizeof(int));

    v.t[0]=1;
    v.t[1]=5;

    fct(&v,&w);

    for (i=0; i<2; i++)
        printf("%d \t",w.t[i]);


    puts("");

    free(v.t);
    free(w.t);

    return 0;
}

是的,您正在泄漏内存。w.t永远不会释放。
还可以通过指针而不是值传递结构。返回向量也很昂贵

您的新程序可以如下所示:

#include <stdio.h>


typedef struct {
    int x;
    int *t;
}vector;

void fct (vector *v, vector * w){

    int i;

    w->x = v->x;

    for (i=0; i<w->x; i++)
        w->t[i]=2*v->t[i];
}


int main (){
    int i;
    vector v;
    vector w;

    v.x=2;

    v.t = malloc(2*sizeof(int));
    w.t = malloc(2*sizeof(int));

    v.t[0]=1;
    v.t[1]=5;

    fct(&v,&w);

    for (i=0; i<2; i++)
        printf("%d \t",w.t[i]);


    puts("");

    free(v.t);
    free(w.t);

    return 0;
}
我非常担心它是否会导致内存泄漏,以及如何修复它

确实如此。在
main()
中,分配内存并指向
v.t
;然后用
fct()
返回值中的一个指针覆盖该指针。原始指针丢失,并且没有它的其他副本,因此指向的内存泄漏

哦,我知道如果我定义另一个向量,比如说w,那么w=fct(v),它会解决这个问题,但是我需要一个不同的方法,一个即使函数返回到原始向量也能工作的方法

随着每一个动态内存分配都有义务释放这个内存,你可以把这个内存与一个内存指针的一个副本联系起来,作为一种名义标签。将标记转移到指针的其他副本。但是,如果带有标记的副本超出范围或被其他值覆盖,则会将指向的内容泄漏到内存

考虑一下这如何适用于您的案例:

  • 分配内存并将指针分配给
    v.t
    。这最初是指向已分配内存的指针的唯一副本,因此释放该内存的义务与此相关

  • 您将
    v
    的副本(包括
    v.t
    的副本)传递给函数
    fct()
    。您有两种选择:释放的义务可以保留在
    v.t
    的原始副本上,也可以转移到函数接收的副本上。这是
    fct()定义的固有特征
    ,并且应该随附文档--您不能逐个调用进行选择。由于
    fct()
    没有释放指针,因此您隐式选择了释放以保留原始副本的义务

  • fct()
    执行自己的分配并返回结果指针的一个副本;这是函数执行后唯一幸存下来的副本,因此释放的义务必须伴随着它

  • 当原始
    v.t
    有义务释放时,用不同的值覆盖原始
    v.t
    会泄漏原始内存。仍然有义务释放
    v.t
    的(新)值,但无法再访问旧的动态分配内存

  • 现在您有了一个选项:是否将义务作为函数调用的一部分转移到free。假设您确实转移了它;在这种情况下,
    fct()
    必须在它返回之前执行该
    free()
    。但是,在这种情况下,
    main()
    在调用
    fct()
    后,无论是否用该函数的结果覆盖
    v
    ,都不得使用
    v.t
    的原始值

    因此,您有一个选择:
    fct()
    负责释放
    v.t
    (如果愿意,它可以传递给另一个函数,或者它可以通过返回值返回给调用方),或者
    fct()
    不承担这一责任。它的调用者需要做出相应的行为。你不能两全其美

    我非常担心它是否会导致内存泄漏,以及如何修复它

    确实如此。在
    main()
    中,分配内存并指向
    v.t
    ;然后用
    fct()
    返回值中的一个指针覆盖该指针。原始指针丢失,并且没有它的其他副本,因此指向的内存泄漏

    哦,我知道如果我定义另一个向量,比如说w,那么w=fct(v),它会解决这个问题,但是我需要一个不同的方法,一个即使函数返回到原始向量也能工作的方法

    <每一个动态内存分配都有义务释放那个内存。你可以考虑把这个内存的指针与一个内存的指针相关联,作为一种名义标签。你可以自由地(名义上)将标签传输到指针的不同副本。