繁体   English   中英

结构中的共享对象:在调用程序和库之间(在c中)

[英]shared objects within a struct: between a calling program and library (in c)

在一个单独的库中,我们有一个结构:

typedef struct bsmat{
int m;
int *n;
double **d;
} bs;

其中** d是指向双数组的指针数组。

bs *new_bs(int n, double **d);

有两种用例:

(a)主应用程序分配多个双矩阵并调用库来构造结构。

b = new_bs(5, p)

(b)或者,作为调用函数的结果,库可以生成对象:

bs *add(bs *a, bs *b);

在第二种情况下,图书馆拥有** d并且可以在必要时释放它。 在第一种情况下,应用程序已分配数组,并且库可以读取/写入它。 我不清楚谁应该释放什么,什么时候?

允许主应用程序拥有结构成员是一个问题吗? 这种方法有什么问题? 有哪些替代方案? 我们试图避免来回复制大量数组。

谢谢

TR

一般而言,图书馆记录它与使用其服务的应用程序所做的“合同”非常重要。 库编写器记录了库所做的所有分配以及应用程序需要释放的内容。 像任何合同一样,当它简单而一致时很好。

在这种特殊情况下,我认为图书馆还应该提供:

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时,减少它的引用计数。 如果它变为零,则释放它。 在某种程度上,它是高级语言为您所做的事情,并且非常有效地保持资源管理的合理性。

所以没有人拥有阵列,但无论谁最后需要它,都可以释放它。

当然,这需要更多的工作并使代码复杂化,所以尽量保持平衡。 您拥有的每个结构都不需要它,但仅适用于您需要保留多个引用的结构。

我认为引用计数对于这个问题来说太过分了。 但是你的界面需要更准确地指定谁拥有*b而不仅仅是b->d 我完全不清楚图书馆知道什么时候“必要”(如你所说)释放b->d

我将扩展界面如下:

  1. bs *类型的每个指针都是外部管理内部管理的 函数new_bs返回一个外部管理的指针; function add返回内部管理的。

  2. 返回类型为bs *的指针的每个函数都应该说明结果的管理是内部还是外部。

  3. 你可能应该提供功能

     void bs_free_ext(bs **); // free *bs and set *bs = NULL (external mgmt) void bs_free_int(bs **); // free *bs and set *bs = NULL (internal mgmt) 

    bs_free_ext只释放*bs ; bs_free_int释放*bs(*bs)->d

  4. 为了安全起见,我还要添加记录每个结构的存储管理的字段,并且我会对任何分配或释放的函数进行断言。 (原因:与分配或释放的成本相比,断言检查很便宜。)

如果您可以在Linux上运行您的应用程序,那么使用valgrind进行内存检查是一个优势。

PS内存管理的细节几乎渗透到每个界面这一事实是我们为了获得C语言编程的好处而付出的代价之一。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM