我是一个C编程的初学者,我相信这个问题已经解决了,但是我找不到太多的答案。在我的程序中,我有一个BST(二进制搜索树)节点的实现:
typedef struct bstnode{
char *key;
void *value;
struct bstnode *left;
struct bstnode *right;
}bstnode;
其中我需要value为void*,以便将同一结构用于不同的目的。然而,我担心的是,在这样做的过程中,我允许在我的程序中有更多的错误和不稳定的可能性。例如:在许多情况下,关键字指向存在于堆栈中的值。这很好但是,有时我需要对密钥执行动态分配。有时,价值也是动态分配的。这意味着对于我创建的每一棵树,我必须执行不同的释放例程(并且,如果值是另一个动态分配的结构,我还需要确保正确地释放该结构)。当然,我可以跟踪哪个结构是哪个结构,但我担心这可能会失控并导致内存泄漏,以及更少的“可维护”代码库(例如,“可维护”代码库)。必须为特定的使用情况做出特定的解除分配功能)。我的问题是:我做的是不是不好的练习?有没有比为结构的每个用例编写函数更好的方法呢?
3条答案
按热度按时间cbjzeqam1#
管理对象的生命周期是编程中的一个非常大的主题,转移管理对象生命周期的权限也是如此。有多种方法可以解决这个问题。
cookie
,您可以传递堆栈上分配的所有键的索引,并将它们从free()
中排除。总的来说,这是你可以考虑的方式。您可能对https://docs.gtk.org/glib/struct.Tree.html感兴趣。
zc0qhyus2#
我做的是不是不好的练习?有没有比为结构的每个用例编写函数更好的方法呢?
这些都是好问题。你注意到了一些重要的细节。
底线是,如果你想适应最一般的情况,你的节点可以包含指向不同类型和出处的值的指针,那么是的,你需要以某种方式提供信息,允许你的树操作例程在需要时触发正确的清理。
一些可能性包括:
9jyewag03#
在数据结构中处理这种情况的最常见方法是认识到数据结构将指向它们没有分配和控制的数据。
所以处理这个问题的常用方法是在C程序中创建可以添加到数据结构中的对象。但是执行分配的代码层也应该执行释放。它还应该避免在BST中留下一个指向已释放对象的节点。
因此,为您的API提供一个
bst_delete(bsttree*, char* key)
函数,它将从bst中删除bstnode(并释放它)。但不会释放指向的实际对象。因为那不是它的工作。调用代码应该先调用
bst_delete()
,然后调用free()
,这是需要删除的对象。不要将在堆栈上分配的对象添加到
bsttree
,除非在使用该堆栈上下文的函数的生存期内,树也被销毁。销毁bsttree
时,您需要删除它的所有节点以避免内存泄漏。