所以这是我的代码:
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;
}
我非常担心它是否会导致内存泄漏,以及如何解决这个问题。
哦,我知道如果我定义另一个向量,那就说w,这样
w = fct(v)
它会清除问题,但我需要一个不同的方法,即使函数返回到原始向量也能工作。
答案 0 :(得分:4)
v.t=malloc(2*sizeof(int));
在此您将已分配的内存分配给v.t
。
v=fct(v);
然后在此处使用v
返回的内容覆盖fct
的所有字段。这会丢弃v.t
的旧值,导致内存泄漏。
在free
结束时对main
的调用释放了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);
答案 1 :(得分:1)
确实如此。向量t被分配两次,并释放一次。整个架构看起来有问题。
答案 2 :(得分: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;
}
输出:
2 10
答案 3 :(得分:0)
我非常担心它是否会导致内存泄漏,以及如何解决这个问题。
确实如此。在main()
中,您可以为其分配内存并指向v.t
;然后用fct()
的返回值覆盖该指针。原始指针丢失,你没有其他副本,所以指向内存泄露。
哦,我知道如果我定义另一个向量,让我们说w,这样w = fct(v)就可以解决问题,但是我需要一种不同的方法,即使是函数返回到原始向量。
每次动态内存分配都有释放内存的义务。您可以认为该义务仅与指向该内存的指针的一个副本相关联,作为一种概念标记。您可以自由(理论上)将标记转移到指针的不同副本。然而,如果带有标签的副本超出范围或被不同的值覆盖,那么你会泄漏指向的内存。
考虑一下这适用于您的情况:
您分配内存并指定指向v.t
的指针。这最初是指向已分配内存的指针的唯一副本,因此释放该内存的义务与之相关。
您将v
的副本(包括v.t
的副本)传递给函数fct()
。您有两种选择:免费义务可以保留v.t
的原始副本,也可以转移到该功能收到的副本。这是fct()
定义的固有特征,应该用它来记录 - 你不能在逐个呼叫的基础上进行选择。由于fct()
没有释放指针,因此您隐含地选择了自由保留原始副本的义务。
fct()
执行自己的分配并返回结果指针的副本;这是执行该功能后唯一幸存的副本,因此免费义务必须随之而来。
通过使用不同的值覆盖原始v.t
,同时它有义务释放,您泄漏原始内存。仍然有义务释放v.t
的(新)值,但是没有任何方法可以访问旧的动态分配的内存。
现在你有一个选项:是否将义务转移到函数调用的一部分。假设你确实转移了它;在这种情况下,fct()
必须在返回之前执行free()
。但是,在这种情况下,main()
在调用v.t
后不得使用fct()
的原始值,是否会使用该函数的结果覆盖v
。
所以你有一个选择:fct()
负责释放v.t
(它可以传递给另一个函数,如果它希望,或者它可以通过它的返回值返回给调用者) ,或fct()
不承担这一责任。其呼叫者需要相应的行为。你无法双管齐下。