2016-09-25 86 views
0

我试图避免在我的代码中发生内存泄漏。我需要取消分配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 
+1

听起来像你的pImage正在使用这些值。为什么他们需要在你的添加中被释放?为什么不在“CleanUpVectorGraphic”函数中释放它们? – NullEntity

+1

如果你需要一个结构指针,那么你为什么要首先释放它呢?国际海事组织,你应该解释你想做什么,因为我不明白你想要达到什么。 –

+1

@Disillusioned是否可以从另一个函数访问这些结构?我知道我可以免费(pImage);和它的所有内容在一个循环中。但是线,pSecond和pElement如何。我如何从清理功能访问它们? – Calidreaminn

回答

1

我怎样才能使这些值我add函数内本地?

不可能显式释放本地分配的内存。 本地免费也有些记忆。一旦释放,内存插槽将无法访问,并且内部存储的数据将丢失。

在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 
       +---------+      +---------+ 

正如你所看到的,你离开功能之后,你有,你没有任何指针动态分配的内存内存泄漏。避免这种情况的一种方法是返回指针(以便将新内存插槽的地址传递给调用函数)或将其存储在某处以便稍后释放它。也可以在调用函数之前分配内存并将其作为参数传递给函数。这真的取决于你的应用程序。