C语言自定义vector扩容后外部指针指向异常问题排查求助
问题根因
C语言默认是值传递,你当前的insert函数的形参vector_t* v是外部实参指针的拷贝,函数内部修改v = cv的操作只会修改这个局部拷贝的指向,完全不会影响外部原来的vector指针。这就导致你在扩容逻辑里free(v)之后,外部的实参指针直接变成了野指针,下次调用insert时传入的就是已经被释放的内存地址,才会出现乱码的容量、大小值。
修复方案
有两种可行的修复方案:
方案1:仅扩容数据区(更推荐)
vector的结构体本身仅存储元数据,不需要随扩容重新分配,只需要重新分配p_data指向的数组即可,从根源避免指针指向修改的问题,同时性能更高,也符合动态数组的常规实现逻辑。
修改后的insert代码如下:
void insert(vector_t* v, int val){ if(v == NULL){ printf("ERROR: vector == NULL"); return; } printf("BCapacity: %d\n", v->capacity); printf("BSize: %d\n", v->size); if(v->size >= v->capacity){ // 仅扩容数据数组,不改动vector结构体本身 int new_cap = v->capacity * 2; int* new_pdata = (int*)realloc(v->p_data, sizeof(int) * new_cap); if(new_pdata == NULL){ printf("ERROR: realloc failed\n"); abort(); } v->p_data = new_pdata; v->capacity = new_cap; printf("INCapacity: %d\n", v->capacity); printf("INSize: %d\n", v->size); } v->p_data[v->size] = val; v->size++; printf("Capacity: %d\n", v->capacity); printf("Size: %d\n", v->size); }
该方案不需要修改原有外部调用逻辑。
方案2:使用二级指针修改外部实参
如果你确实需要重新分配整个vector结构体,就需要传入二级指针,让函数可以修改外部实参的指向:
修改后的insert代码如下:
// 形参改为二级指针 void insert(vector_t** v, int val){ if(v == NULL || *v == NULL){ printf("ERROR: invalid vector pointer\n"); return; } vector_t* real_v = *v; printf("BCapacity: %d\n", real_v->capacity); printf("BSize: %d\n", real_v->size); if(real_v->size >= real_v->capacity){ vector_t* cv = createVector(real_v->capacity * 2); for(int i = 0; i < real_v->capacity; i++){ cv->p_data[i] = real_v->p_data[i]; } cv->size = real_v->size; free(real_v->p_data); free(real_v); // 修改外部实参的指向 *v = cv; printf("INCapacity: %d\n", (*v)->capacity); printf("INSize: %d\n", (*v)->size); } (*v)->p_data[(*v)->size] = val; (*v)->size++; printf("Capacity: %d\n", (*v)->capacity); printf("Size: %d\n", (*v)->size); }
对应的调用方式也需要同步修改,传入指针的地址:
// 原调用方式 insert(v, 数值); 改为: insert(&v, 123);
内容的提问来源于stack exchange,提问作者Dejavu
相关产品推荐
相关产品推荐

