C API 允许自动存储和分配存储

C API allowing for both automatic and allocated storage

提问人:cesss 提问时间:2/21/2021 更新时间:2/21/2021 访问量:78

问:

我正在编写一个具有结构的 API ,例如

struct datast{
int a;
int *items;
size_t numitems;
};

我提供了释放此类结构内容的函数(类似于 C++ 析构函数所做的方式)。没有提供构造函数,因为我要求对它们进行零初始化(该字段必须是初始化时的指针,这使得它适合以后和)。.itemsNULLrealloc()free()

但是,我提供了一个函数,该函数会相应地增加。additem()realloc().items.numitems

但是,由于这些结构很小,因此我鼓励使用指定的初始值设定项和复合文字,以便用户可以在可能的情况下使用单行代码方便地创建这些对象,而无需手动调用 .additem()

但是,如果使用指定的初始值设定项(或从复合文本分配给它们)初始化此类结构,则该字段将具有自动存储,而不是分配的存储。因此,如果你稍后将这个结构传递给“释放”函数/析构函数,你将使用非法指针(指向自动存储)进行调用。.itemsfree()

是的,我知道措辞可能是“不要为未调用 additem()的对象调用析构函数”......但这看起来真的很笨拙,而且似乎是糟糕的设计。

不知何故,这就像我必须决定所有这些对象是否应该具有自动存储或分配存储,而不给用户这两种可能性。

你有没有遇到过这样的情况?我可以使用任何一种设计来为自动存储和分配存储提供干净优雅的界面吗?

c 动态内存分配 自动存储

评论

0赞 harper 2/21/2021
因此,您想在任意对象上标识它是否在堆上,并为可能成为堆项的所有内容调用 free 函数?建议:切勿这样做。1) 这是编译器和运行时 lib 的依赖 2) 如果列表中有一个堆栈或数据段对象,您将如何确保该对象中的指针仍然指向未被“编辑”的内存?!用你的精力来获得更好的设计。free
0赞 cesss 2/21/2021
@harper:没错,那是我不想做的,当然我也不会那样做。我要求的是最好的设计。但这就像我被迫放弃支持这个 API 的单行初始化器,这很可悲。我要求一些可以容纳两种存储的设计。
1赞 Peter - Reinstate Monica 2/21/2021
一如既往:由用户来跟踪。additem() 函数需要一个标志来告诉它是否释放()原始数据。如果项目需要释放,您可以(如果它只是关于项目而不是关于结构本身)在结构中设置一个标志,该标志由您的“工厂”(或 additem())设置。

答:

1赞 Clifford 2/21/2021 #1

添加布尔成员 。您强制执行的零初始化将使 .然后会设置它:items_allocatedfalseadditem()true

struct datast
{
    int a;
    int *items;
    bool items_allocated ;
    size_t numitems;
} ;

然后你的析构函数可以有类似的东西:

if( d->items_allocated )
{
    free( d->items ) ;
    d->items = NULL ;
}
d->numitems = 0 ;
...

评论

0赞 cesss 2/21/2021
我认为你的解决方案是一个很好的解决方案,我很可能会将其标记为公认的答案。此外,与此同时,我意识到了一个我没有想到的可能情况:如果用户调用一个将数组初始化为自动存储的结构怎么办?同样,在这种情况下,如果为 false 且不是 ,则应返回错误。additem()additem()items_allocateditemsNULL
0赞 cesss 2/21/2021
无论如何,我觉得指定的初始值设定项和复合文字使用起来很不错,但如果你碰巧有带有数组成员的结构,就会产生一种“戏剧性的张力”,因为你发现自己正处于一场自动与分配的战争中。