我创建了如下结构体:
typedef struct header{
int hc;
char src[18];
char dst=[18];
char reason[15];
char d[3];
char m[3];
char y[4];
struct measurements{
char h_ip[17];
int h_ttl;
int h_id;
float h_rtt;
}HOPS[100];
}HEADER;
INSIDE MAIN:
HEADER *head;
for(...){
head=(HEADER*) malloc(sizeof(HEADER));
.....
free(head);
}
上面的malloc也会自动为内部结构分配内存吗?而且,我还面临着一个奇怪的问题。在释放报头之后,我仍然能够打印head->HOPS[I].h_ip的值。我是否应该显式地释放内部结构体,以便甚至清除值?
是的,它为内部结构分配内存。你不需要单独释放内部结构。如果你在结构体内部定义了一个指针,在这种情况下,你必须为结构体的指针成员单独分配,并单独释放它。
考虑释放内存作为一个黑盒。你所知道的是,在释放之后,你不应该引用已释放的内存。
您可能会发现该内存块仍然存在,并且仍然包含一些旧值。没关系:它刚刚被标记为已释放,可能很快就会被分配器再次使用。
例如,当您再次调用malloc并意识到刚刚分配的块包含旧结构的值时。这种事时有发生,但没关系。
因此,在head
的错误声明问题解决后:
free
返回先前分配给堆的内存块。它不清除任何内容(出于性能原因)。但是,之后不应该再访问该块了。这样做会导致未定义行为,并可能让您的计算机飞出窗口。
最坏的可能是…没有什么……是的,你甚至可能没有注意到任何奇怪的事情发生。但是,这并不意味着您的程序可以正常运行,它只是没有显示任何症状。为了捕获非法访问,可以在free
指向对象后将指针设置为NULL
。有些操作系统会捕获对空指针地址附近的地址的访问,但这并不能保证。无论如何,这是一种很好的做法,而且没有害处。
对于您的另一个问题:malloc
分配了一个足够大的内存块来存储您作为参数传递的许多字节。如果不能,它将返回一个空指针。你应该总是检查malloc
&友元返回一个有效指针(即不是空指针)。
int *p = malloc(sizeof(int));
if ( p == NULL ) {
error: out of memory
}
...
注意省略了对malloc
结果的强制转换。在C语言中,您不应该将void *
转换为malloc
&朋友(但也包括其他地方的朋友)。就像你没有为free(head)
做的那样。顺便说一句,两者都采用相同的类型:void *
。(那么为什么只投一个而不投另一个呢?)注意,在C语言中,任何对象指针都可以自由地赋值给void *
,而不需要强制转换。警告函数在C标准中是没有对象!
最后:sizeof(HEADER)
返回struct
的大小。当然,这包括所有字段。嵌套的struct
是一个字段。指向另一个结构体的指针是一个字段。对于后者,请注意:指针本身是一个字段,但是不是它所指向的 !如果这是另一个结构体,你必须分别malloc
**和free
(记得我上面写的)。
但是当你没有指针在你的struct
,这不是你的问题在这里。(请记住,如果您继续编程,您最终将需要它!)