C - 在函数内部分配内存时,谁负责内存分配?
C - Who is responsible for memory allocation when memory is allocated inside a function?
我正在尝试提升我的 C 级游戏。我目前正在使用 Kyle Loudon 的书“Mastering Algorithms with C”。目前我正在研究数据结构,特别是堆栈。我将在此处使用的代码示例并非直接来自本书,而是为了便于阅读而稍作修改。我在网上看过,但没有找到任何问题的答案。
我在 C 编程中经常听到的一条常见规则是“分配内存的人负责释放它”。这似乎是一个简单的规则。但是,当我尝试创建一个函数来将新的堆栈元素压入堆栈顶部时,我有点不确定。
密码
StackElmt 是驻留在堆栈中的元素。在堆栈上执行任何操作之前,stack_init 需要是 运行。之后 stack_push 将新元素压入栈顶,stack_pop 将它们从栈中弹出。
typedef struct StackElmt_ {
void *data;
struct StackElmt_ *next;
}StackElmt;
typedef struct Stack_
{
int size;
StackElmt *top;
}Stack;
void stack_init(Stack *stack)
{
stack->size = 0;
stack->top = NULL;
}
void stack_push(Stack *stack, void *data)
{
StackElmt *element = calloc(1, sizeof(StackElmt));
element->data = data;
element->next = stack->top;
stack->top = element;
stack->size++;
}
void stack_pop(Stack *stack, StackElmt **element)
{
*element = stack->top;
stack->top = (*element)->next;
stack->size--;
}
问题描述
我觉得很奇怪 stack_push 将内存分配给堆但 stack_pop 没有释放它。我觉得如果 stack_push 分配内存,内存管理就变成了这些 Stack 函数的开发者的责任,而不是用户的责任。
相反,我想做这样的事情:
void stack_push(Stack *stack, StackElmt *element, void *data)
{
element->data = data;
element->next = stack->top;
stack->top = element;
stack->size++;
}
输入指向 StackElmt 的指针,用户可以自行选择如何分配它。
总结
我的问题是:
- 在 stack_push() 中分配内存但在 stack_pop() 中未释放内存的代码是否被认为是好的设计?在 stack_pop() 中明确评论用户负责 StackElmt 内存是否会使设计更好?
- 书上还有一个叫做“destroy_stack”的函数,就是破坏栈的。其中,“stack_pop”和一个指针指向的自定义函数(建议免费)对于Stack中的每个元素都是运行。从负责内存管理的用户角度来看,这个“销毁”功能是否更清楚?
- 内存分配完全由用户分配(见我修改的stack_push)还是由程序完成更好?
提前谢谢大家!
stack_pop()
不应该 return StackElmt
,它应该 return 元素中的 data
。这反映了 stack_push()
.
的动作
然后它可以释放元素。
void stack_pop(Stack *stack, void **data)
{
if (!stack->top) {
// report stack underflow error somehow
return;
}
*data = stack->top->data;
StackElmt *temp = stack->top;
stack->top = temp->next;
stack->size--;
free(temp);
}
函数 stack_pop 不应公开节点类型,而是 return 数据。使用这种方法,可以在函数中释放节点。我们还应该确保在弹出元素之前堆栈不为空。这是修改后的版本:
void stack_pop(Stack *stack, void **data)
{
StackElmt *oldTop;
assert(stack != NULL);
assert(stack->size > 0);
*data = stack->top->data;
oldTop = stack->top;
stack->top = stack->top->next;
free(oldTop);
stack->size--;
}
您可能还想定义一个 stack_size 函数,以便客户端可以在调用 [=21 之前检查堆栈是否为空=].
我正在尝试提升我的 C 级游戏。我目前正在使用 Kyle Loudon 的书“Mastering Algorithms with C”。目前我正在研究数据结构,特别是堆栈。我将在此处使用的代码示例并非直接来自本书,而是为了便于阅读而稍作修改。我在网上看过,但没有找到任何问题的答案。
我在 C 编程中经常听到的一条常见规则是“分配内存的人负责释放它”。这似乎是一个简单的规则。但是,当我尝试创建一个函数来将新的堆栈元素压入堆栈顶部时,我有点不确定。
密码
StackElmt 是驻留在堆栈中的元素。在堆栈上执行任何操作之前,stack_init 需要是 运行。之后 stack_push 将新元素压入栈顶,stack_pop 将它们从栈中弹出。
typedef struct StackElmt_ {
void *data;
struct StackElmt_ *next;
}StackElmt;
typedef struct Stack_
{
int size;
StackElmt *top;
}Stack;
void stack_init(Stack *stack)
{
stack->size = 0;
stack->top = NULL;
}
void stack_push(Stack *stack, void *data)
{
StackElmt *element = calloc(1, sizeof(StackElmt));
element->data = data;
element->next = stack->top;
stack->top = element;
stack->size++;
}
void stack_pop(Stack *stack, StackElmt **element)
{
*element = stack->top;
stack->top = (*element)->next;
stack->size--;
}
问题描述
我觉得很奇怪 stack_push 将内存分配给堆但 stack_pop 没有释放它。我觉得如果 stack_push 分配内存,内存管理就变成了这些 Stack 函数的开发者的责任,而不是用户的责任。
相反,我想做这样的事情:
void stack_push(Stack *stack, StackElmt *element, void *data)
{
element->data = data;
element->next = stack->top;
stack->top = element;
stack->size++;
}
输入指向 StackElmt 的指针,用户可以自行选择如何分配它。
总结
我的问题是:
- 在 stack_push() 中分配内存但在 stack_pop() 中未释放内存的代码是否被认为是好的设计?在 stack_pop() 中明确评论用户负责 StackElmt 内存是否会使设计更好?
- 书上还有一个叫做“destroy_stack”的函数,就是破坏栈的。其中,“stack_pop”和一个指针指向的自定义函数(建议免费)对于Stack中的每个元素都是运行。从负责内存管理的用户角度来看,这个“销毁”功能是否更清楚?
- 内存分配完全由用户分配(见我修改的stack_push)还是由程序完成更好?
提前谢谢大家!
stack_pop()
不应该 return StackElmt
,它应该 return 元素中的 data
。这反映了 stack_push()
.
然后它可以释放元素。
void stack_pop(Stack *stack, void **data)
{
if (!stack->top) {
// report stack underflow error somehow
return;
}
*data = stack->top->data;
StackElmt *temp = stack->top;
stack->top = temp->next;
stack->size--;
free(temp);
}
函数 stack_pop 不应公开节点类型,而是 return 数据。使用这种方法,可以在函数中释放节点。我们还应该确保在弹出元素之前堆栈不为空。这是修改后的版本:
void stack_pop(Stack *stack, void **data)
{
StackElmt *oldTop;
assert(stack != NULL);
assert(stack->size > 0);
*data = stack->top->data;
oldTop = stack->top;
stack->top = stack->top->next;
free(oldTop);
stack->size--;
}
您可能还想定义一个 stack_size 函数,以便客户端可以在调用 [=21 之前检查堆栈是否为空=].