You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

void指针数组操作实现正确性咨询:元素获取与销毁

关于void指针数组容器的函数实现验证问题

用户定义了如下动态数组结构体:

typedef struct vector 
{
  void **array;
  size_t size;
}vector;

随后实现了两个元素访问函数与一个销毁函数,希望验证实现的正确性:

  1. 用于获取指定位置元素引用的函数:
void **get_at(vector *this, size_t pos) 
{
   assert(pos >=0 && pos < this->size);

   return &this->array[pos];
}
  1. 用于获取指定位置元素指针的函数:
void *at(vector *this, size_t pos) 
{
   assert(pos >=0 && pos < this->size);

   return this->array[pos];
}
  1. 用于销毁数组的函数:
void destroy(vector *this)
{
  free(this->array);
  free(this);
}

一、元素访问函数的正确性验证

  • at函数完全正确:它直接返回容器中存储的第pos个void*指针,完全符合“获取指定位置元素指针”的需求。
  • get_at函数实现正确,但需注意使用场景:它返回的是容器内部存储该void*指针的地址(void**类型),这确实是“元素的引用”——通过这个指针可以修改容器中存储的void*值(比如替换为其他指针)。但要注意,该返回值指向容器内部内存,若容器底层数组发生扩容重分配,这个地址会失效,不能长期持有。

额外补充:size_t是无符号类型,pos >= 0的判断完全多余(无符号数永远不会小于0),编译器大概率会优化掉这个判断,可直接写成assert(pos < this->size)。

二、销毁函数的合理性分析

destroy函数是否足够,核心取决于容器中void*指针指向的内存归属:

  • 如果容器仅负责存储指针,元素内存由外部代码管理(比如用户自行分配/释放元素内存),那么当前destroy函数就足够——只需释放容器自身的底层数组array和结构体this的内存即可。
  • 如果容器设计为负责管理元素内存(比如插入函数会为元素分配内存),则必须遍历数组,逐个调用free释放每个array[pos]指向的内存,之后再释放array和this,否则会造成内存泄漏。

举两个典型场景:

  • 外部管理元素内存的使用场景:
vector* v = create_vector();
int* num = malloc(sizeof(int));
*num = 10;
push_back(v, num); // 仅将num指针存入容器
// 调用destroy(v)后,需自行free(num),否则内存泄漏

这种情况无需在destroy中遍历释放元素。

  • 容器管理元素内存的实现场景:
void push_back(vector* v, int value) {
    int* num = malloc(sizeof(int));
    *num = value;
    v->array[v->size++] = num;
}

此时destroy必须遍历释放每个array[pos],否则这些num的内存会永久泄漏。

内容的提问来源于stack exchange,提问作者Calvince

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 14:45:24