我想在链表上更好地理解malloc()。这是否为指向列表的指针以及其中的字段创建内存? 如:
SomeStruct * someStructPtr = (SomeStruct *) malloc(sizeof(SomeStruct));
除此之外,如果我试图释放此节点及其中的字段。我是否需要遍历所有字段(请参阅下面的代码)。这只是释放指针(从上面的行创建)还是释放指针和字段。
free(someStructPtr);
更直接的例子。我有一个List的结构,我试图为这个结构分配空间及其创建时的字段。我想确保正确创建,删除和使用stdrup()。我的代码如下:
结构声明:
typedef struct ListNode_st
{
char * str;
struct ListNode_st * next;
} List;
创建节点:
List * List_createNode(const char * str){
List * listPointer = (List *) malloc(sizeof(List));
//make sure there was enough memory
if(listPointer == NULL)
return NULL;
//malloc for next
listPointer.next = (List *) malloc(sizeof(List *));
if(listPointer.next == NULL)
return NULL;
listPointer.next = NULL;
//malloc for str
listPointer.str = strdup(str);
//make sure enough space for the string to be copied
if(listPointer.str == NULL)
return NULL;
//return value
return listPointer;
}
删除节点:
void List_destory(List * list){
//base case -- (last item)
if(list == NULL)
return;
//recurse case -- (there are more items)
List_destroy(list->next);
if(list->str != NULL)
free(list->str);
if(list->next != NULL)
free(list->next);
free(list);
}
答案 0 :(得分:3)
请不要从malloc()
投射返回值。
malloc(sizeof(SomeStruct))
为一个结构分配足够的内存,然后必须初始化结构中的每个字段。
calloc(1, sizeof(SomeStruct))
执行相同的操作,但结构的每个字节都初始化为0
。 malloc()
和calloc()
对您的结构一无所知,只是分配您要求的内存量。它们返回一个void*
指针,以便它们可以用于任何他们既不知道也不关心的数据类型。
当你来到free()
分配的内存时,同样适用 - free()
对你的结构一无所知,或者即使它是一个结构。在free()
结构的内存之前,由free()
在该结构中的任何内存分配决定你。它没有释放结构。它释放了结构所在的内存。
所以答案是肯定的,你需要遍历整个数据结构,否则任何嵌套的内存分配指针都将丢失,导致内存泄漏。
答案 1 :(得分:2)
List * List_createNode(const char * str){
List * listPointer = (List *) malloc(sizeof(List));
if(listPointer == NULL)
return NULL;
listPointer->next = NULL;
listPointer->str = strdup(str);
if(listPointer->str == NULL){
free(listPointer);
return NULL;
}
return listPointer;
}
void List_destory(List * list){
if(list == NULL)
return;
List_destroy(list->next);
free(list->str);
free(list);
}
答案 2 :(得分:2)
在我们解决你的问题之前,先让我们热身。
int x = 42;
x的记忆来自哪里?分配了吗?哪里?如果这一行在函数内,答案是:它是一个"自动"变量和它使用的内存在堆栈中。
int * y = NULL;
y的记忆从何而来?此处没有致电malloc()
,但y
存在。
到目前为止,您应该能够回答问题的第一部分。在这种情况下,malloc()
没有为指针分配内存。
struct Node
{
struct Node * next;
int value;
};
void InitNode( Node *node, int value )
{
if(NULL != node)
{
node->next = NULL;
node->value = value;
}
}
// Not on HEAP, not on stack! Where?
// This one gets its memory from "initvars" section.
int foo = 69;
int main( int argc, const char * argv[] )
{
struct Node n1; // instance located on stack...
InitNode(&n1); // no malloc() to be seen...
// Instance located on HEAP, but n2, the pointer is located on stack,
// just like an int x = 42 would be.
struct Node *n2 = malloc(sizeof(struct Node));
}
所以,显然是为了解释malloc()
需要了解不同类型的内存以及如何处理它。
到目前为止,我们已经看到"自动"又名"堆栈记忆",我们看到" initvars"记忆。我们看到"堆"记忆。 malloc()是用于在堆上分配内存的函数。
最后,至少还有其他类型的内存我不会在这里提及。
答案 3 :(得分:1)
这是否为指向列表的指针以及其中的字段创建内存?
给出你的结构类型
typedef struct ListNode_st
{
char * str;
struct ListNode_st * next;
} List;
以下调用将为该结构的实例创建内存:
List *l = malloc( sizeof *l ); // note no cast, operand of sizeof
l
指向一块大到足以包含两个指针的内存块;但是,没有为str
或next
分配任何内容以将指向。您必须分别为字符串和下一个节点分配内存:
l->str = malloc( N * sizeof *l->str ); // allocate N characters
或
l->str = strdup( str );
请注意,在大多数链接列表实现中,您在创建新节点时不会为next
分配内存;该字段旨在指向列表中另一个先前分配的节点。在当前节点之后插入节点时,将设置它。
除此之外,如果我试图释放此节点及其中的字段。我是否需要遍历所有字段(请参阅下面的代码)。这只是释放指针(从上面的行创建)还是释放指针和字段。
在删除整个节点之前,您需要先释放所有已分配的成员,例如
free( l->str );
free( l );
释放l
不会释放l->str
指向的内存。