- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
在一个单独的库中,我们有一个结构:
typedef struct bsmat{
int m;
int *n;
double **d;
} bs;
其中 **d 是指向 double 组的指针数组。
bs *new_bs(int n, double **d);
有两个用例:
(a) 主应用分配多个 double 矩阵并调用库构造结构。
b = new_bs(5, p)
(b) 或者,作为函数调用的结果,库可以生成一个对象:
bs *add(bs *a, bs *b);
在第二种情况下,库拥有 **d 并且可以在必要时释放它。在第一种情况下,应用程序已经分配了数组并且库可以读取/写入它。我不清楚谁应该释放什么以及何时释放?
允许主应用程序拥有结构成员是否有问题?这种方法有什么问题?有哪些选择?我们正在努力避免来回复制大量数组。
谢谢
TR
最佳答案
一般来说,图书馆记录它与使用其服务的应用程序签订的“契约(Contract)”很重要。库编写器记录了库所做的所有分配以及应用程序需要释放的内容。与任何契约(Contract)一样,简单且一致的契约(Contract)是好的。
在这种特殊情况下,我想图书馆还应该提供:
void free_bs(bs *b)
{
if (b->d) {
/* free b->d here */
}
/* free rest of the structure */
}
释放结构。在这里释放 d 数组也是有意义的。应用程序具有指向所有 bs
结构的指针,并负责在不再需要时对它们调用 free_bs
。
例如,如果您想保留 d 以供将来使用,那么在完成库操作后,合约会稍微复杂一些。图书馆还可以提供:
double** bs_get_data(bs *b)
{
double **d = b->d;
b->d = NULL;
return b->d;
}
它返回指向 d
的指针,并将该字段留空,以便自由例程知道要跳过它。
bs_get_data()
的文档必须解释它只能被调用一次,并且在这种情况下应用程序负责释放数组。
更新:在回答您的以下评论时:首先,请注意我通过(至少)以下假设简化了问题:d
由单个 bs
引用结构或应用程序。应用程序和库将对数组的单个引用从一个传递到另一个。例如,如果您想要在多个 bs
结构中使用相同的 d
数组,那么我的方法是不够的。
您在评论中提出的标志可能会有所帮助,但不是标准做法,FWIK。在这种情况下,我建议实现一些简单的引用计数。如果 d
是需要共享的资源,将其设为“对象”:
typedef struct {
double **d;
int ref;
} d_t;
用 1 初始化 ref
。在 new_bs()
和所有接收 d
的“副本”的函数中,增加引用计数.当 bs
结构被删除时,或者当您在应用程序中不再需要 d
时,减少它的引用计数。如果它变为零,则释放它。在某种程度上,这就是高级语言为您所做的,并且在保持资源管理健全方面非常有效。
因此没有人拥有该数组,但最后需要它的人会释放它。
当然,这需要更多的工作并使代码复杂化,所以尽量平衡。并非您拥有的每个结构都需要它,但只有那些您需要保留多个引用的结构才需要。
关于c - 结构 : between a calling program and library (in c) 中的共享对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1236133/
我是一名优秀的程序员,十分优秀!