我试图避免代码中的内存泄漏。我需要取消分配pElement,line和pSecond,而不会丢失pImage中的值。因为我需要在打印功能中打印这些值。
我的add函数包含struct GraphicElement * pElements;,struct GraphicElement * pSecond ;, struct point point;。
我使用malloc为每个结构分配内存,然后添加值,然后将最终值传递给pImage。除了我总是最终遇到3次内存泄漏之外,我的所有其他功能都能完美运行。因为我没有自由(pSecond); .... free(pElement)... free(line);
如果我在函数退出之前和将值传递给pImage之后尝试释放它们。我的价值都被抹去了。
如何在本地添加函数中释放这些值?
struct Point
{
int x, y;
};
struct Line
{
Point start;
Point end;
};
struct GraphicElement
{
enum{ SIZE = 256 };
unsigned int numLines; //number of lines
Line* pLines; //plines points to start and end
char name[SIZE];
};
typedef struct
{
unsigned int numGraphicElements;
GraphicElement* pElements; //the head points to pLines
} VectorGraphic;
void InitVectorGraphic(VectorGraphic*); //initializes pImage->pElement
void AddGraphicElement(VectorGraphic*); //Used to add
void ReportVectorGraphic(VectorGraphic*); // prints pImage contents
void CleanUpVectorGraphic(VectorGraphic*); //deallocates memory
答案 0 :(得分:1)
如何在本地添加函数中释放这些值?
无法显式释放本地分配的内存。也不本地免费一些记忆。一旦释放,就无法访问内存插槽,并且内部存储的数据将丢失。
在C中,您有两个分配内存的选项:您可以在堆上或堆栈上分配它。堆上保留的内存插槽可以全局访问,并且在显式释放之前一直保留。堆栈上保留的内容仅在您保持创建的上下文内时才有效。
假设您执行以下代码:
void func()
{
int x = 3; // [2]
int * p = & x; // [3]
}
int main()
{
func(); // [1]
// [4]
return 0;
}
指令[2]
将在堆栈上分配一些内存。第二个([3]
)将执行相同的操作,并将第一个变量的地址存储在新的内存插槽中。函数返回([4]
)后,将释放此内存。从图形上看,这是发生的事情:
Context STACK Address
+---------+
| | 0xa1
main | | 0xa0
+---------+
[1] +---------+
=====> | |
func | | 0xa2
+---------+
| | 0xa1
main | | 0xa0
+---------+
[2] +---------+
=====> | |
func | 3 | 0xa2 <-- x
+---------+
| | 0xa1
main | | 0xa0
+---------+
[3] +---------+
=====> | 0xa2 | 0xa3 <-- p
func | 3 | 0xa2 <-- x
+---------+
| | 0xa1
main | | 0xa0
+---------+
[4] +---------+
=====> | | 0xa1
main | | 0xa0
+---------+
所以如果我在函数中使用malloc。一旦我存在该函数,堆上分配的内存会自动释放吗?
恰恰相反。如果使用像malloc
这样的函数,则会在堆上分配内存槽。因此,如果我们将上面的行[3]
更改为类似
int * p = malloc(sizeof(int)); // [3]
当你离开函数时,堆栈上分配的内存将被释放,但堆上分配的内存将保持分配状态,并且仍可访问,直到你释放它为止。图形化:
HEAP Address Free (y/n)
+---------+
| | 0xb4 - Yes
| | 0xb3 - Yes
+---------+
Context STACK Address
[3] +---------+ +---------+
=====> | 0xb4 | 0xa3 <-- p | | 0xb4 - No
func | 3 | 0xa2 <-- x | | 0xb3 - Yes
+---------+ +---------+
| | 0xa1
main | | 0xa0
+---------+
[4] +---------+ +---------+
=====> | | 0xa1 | | 0xb4 - No !!! Leak !!!
main | | 0xa0 | | 0xb3 - Yes
+---------+ +---------+
正如您所看到的,在您离开函数后,由于没有指向动态分配内存的指针,因此会出现内存泄漏。避免这种情况的一种方法是返回指针(以便将新内存插槽的地址传递给调用函数)或将其存储在某处以便以后释放它。也可以在调用函数之前分配内存并将其作为参数传递给函数。这实际上取决于你的申请。