其他分享
首页 > 其他分享> > 用C 11中的智能指针包装旧的C结构并自动释放它们

用C 11中的智能指针包装旧的C结构并自动释放它们

作者:互联网

我使用的是Word-Net,这是普林斯顿大学90年代开发的旧C库.
该库是用C编写的,仅显示标头,而不显示其实际实现.

我使用的唯一结构是:

SynsetPtr

我调用的两个函数是:

findtheinfo_ds

traceptrs_ds

这两个函数均返回SynsetPtr.

但是,当SynsetPtr代表一个感应列表时,我必须使用

free_syns

而当SynsetPtr用于遍历链接列表(层次树)时,我必须使用

free_synset

Documentation不清楚何时呼叫以及为何呼叫.

这对我来说迅速成为一场噩梦.我花了三天的时间慢慢解决泄漏,两次释放,内存分配等问题.

所以我想知道,有没有办法让我包装这些函数或实际的Structure,并让C管理内存?理想情况下,我希望它们在没有更多引用时释放它们,例如std :: shared_ptr就是这种情况.

知道Synset_Ptr没有析构函数,但是必须调用dealloc函数,这是否可能?

或者,我是否可以包装两个创建(分配)这些结构的函数,以某种方式保留这些对象,并在没有引用的情况下销毁它们?

我将非常感谢任何帮助!

编辑:

这是wn.h中SynsetPtr的确切声明

/* Structure for data file synset */
typedef struct ss {
    long hereiam;       /* current file position */
    int sstype;         /* type of ADJ synset */
    int fnum;           /* file number that synset comes from */
    char *pos;          /* part of speech */
    int wcount;         /* number of words in synset */
    char **words;       /* words in synset */
    int *lexid;         /* unique id in lexicographer file */
    int *wnsns;         /* sense number in wordnet */
    int whichword;      /* which word in synset we're looking for */
    int ptrcount;       /* number of pointers */
    int *ptrtyp;        /* pointer types */
    long *ptroff;       /* pointer offsets */
    int *ppos;          /* pointer part of speech */
    int *pto;           /* pointer 'to' fields */
    int *pfrm;          /* pointer 'from' fields */
    int fcount;         /* number of verb frames */
    int *frmid;         /* frame numbers */
    int *frmto;         /* frame 'to' fields */
    char *defn;         /* synset gloss (definition) */
    unsigned int key;       /* unique synset key */

    /* these fields are used if a data structure is returned
       instead of a text buffer */

    struct ss *nextss;      /* ptr to next synset containing searchword */
    struct ss *nextform;    /* ptr to list of synsets for alternate
                   spelling of wordform */
    int searchtype;     /* type of search performed */
    struct ss *ptrlist;     /* ptr to synset list result of search */
    char *headword;     /* if pos is "s", this is cluster head word */
    short headsense;        /* sense number of headword */
} Synset;

typedef Synset *SynsetPtr;


/* Primary search algorithm for use with programs (returns data structure) */
extern SynsetPtr findtheinfo_ds(char *, int, int, int); 

/* Recursive search algorithm to trace a pointer tree and return results
   in linked list of data structures. */
SynsetPtr traceptrs_ds(SynsetPtr, int, int, int);

/* Free a synset linked list allocated by findtheinfo_ds() */
extern void free_syns(SynsetPtr);   

/* Free a synset */
extern void free_synset(SynsetPtr); 

这基本上就是我所知道的.

编辑2:

即使我使用了以下两个答案,不幸的是,这些函数仍在泄漏字节.

这似乎只发生在:

traceptrs_ds ( ptr, SIMPTR, ADJ, 0 )

该文档几乎没有有关形容词同义词(-synsa)或其他类型(-synsn,-synsv)的信息.

但是,仅通过遵循ptr-> ptrlist&& ptr-&GT nextss;

traceptr_ds迭代所有这些,但是即使使用缩小的测试编,我也找不到避免泄漏的方法.

感谢谁的帮助,非常感谢.

解决方法:

我知道如何使用unique_ptr的巧妙功能解决此问题,该功能的托管类型变为Deleter :: pointer,而不是T *(如果存在前一种类型).

假设您没有Synset的定义或SynsetPtr指向的任何类型,则使用shared_ptr的问题在于它没有切换托管类型的相同功能,并且如果创建了shared_ptr< SynsetPtr&gt ;,构造函数会期望使用SynsetPtr *,但是您的C API函数不会返回该类型.而且我不确定是否使用shared_ptr< remove_pointer< SynsetPtr> :: type>如果您没有解引用SynsetPtr产生的类型的定义,则将编译.

这可能有效,但我不确定.

std::shared_ptr<std::remove_pointer<SynsetPtr>::type>
make_findtheinfo_ds(char *searchstr, int pos, int ptr_type, int sense_num)
{
    return std::shared_ptr<std::remove_pointer<SynsetPtr>::type>
               (findtheinfo_ds(searchstr, pos, ptr_type, sense_num),
                free_syns);
}

std::shared_ptr<std::remove_pointer<SynsetPtr>::type>
make_traceptrs_ds(SynsetPtr synptr, int ptr_type, int pos, int depth)
{
    return std::shared_ptr<std::remove_pointer<SynsetPtr>::type>
               (traceptrs_ds(synptr, ptr_type, pos, depth),
                free_synset);
}

沿着唯一的所​​有权路线,我将创建几个工厂函数,这些函数返回管理SynsetPtrs的unique_ptrs.

对于不同种类的SynsetPtr,我们需要2个单独的删除器

struct sense_list_del
{
    using pointer = SynsetPtr;
    void operator()(SynsetPtr p)
    {
        free_syns(p);
    }
};

struct linked_list_del
{
    using pointer = SynsetPtr;
    void operator()(SynsetPtr p)
    {
        free_synset(p);
    }
};

std::unique_ptr<SynsetPtr, sense_list_del>
make_findtheinfo_ds(char *searchstr, int pos, int ptr_type, int sense_num)
{
    return std::unique_ptr<SynsetPtr, sense_list_del>
               (findtheinfo_ds(searchstr, pos, ptr_type, sense_num));
}

std::unique_ptr<SynsetPtr, linked_list_del>
make_traceptrs_ds(SynsetPtr synptr, int ptr_type, int pos, int depth)
{
    return std::unique_ptr<SynsetPtr, linked_list_del>
               (traceptrs_ds(synptr, ptr_type, pos, depth));
}

标签:c-3,wordnet,c,c11
来源: https://codeday.me/bug/20191011/1891016.html