我正在阅读“C接口和实现”一书,这里有一段代码,我觉得有些不对劲:
void* stack_pop(Stack stack) {
assert(stack->count > 0);
struct Elem* elem = stack->head;
stack->head = elem->next;
stack->count--;
void* x = elem->data;
free(elem);
return x;
}
这是struct stack的定义:
typedef struct Stack {
int count;
struct Elem {
void* data;
struct Elem* next;
} *head;
} Stack;
函数stack_pop
返回指针,但它指向的位置?由于free(elem)
会导致未定义的行为吗?
答案 0 :(得分:3)
stack_pop()
返回对堆栈前端所携带数据的引用,通过此stack_pop()
调用将磁头弹出堆栈。
由于data
被定义为指针(void *)
,此操作将的值复制为x
:
void * x = elem->data;
因此释放elem
(及其成员data
)之后完全没问题。请注意,只有引用(data
)到有效负载free()
ed,而不是引用的有效负载本身(data
指向的内容)。
另请注意,stack_pop()
未检查head
是否为NULL
。在最后一个元素从堆栈中弹出后不要调用它。
答案 1 :(得分:0)
请注意,您可能在元素中使用void*
以允许任何类型的数据存储在此堆栈中。因此,您的“pointer
”可能不一定是指针(您可能必须转换stack_pop()
)。
此外,当你释放指针时,你只释放那段已分配的内存,而不管内存在其结构中可能包含的其他指针。也就是说,当你free()
指针时,free不是“递归的”,它不会free()
Elem内部void* data
指向的内存。