C语言动态数组(vector)添加函数指针后触发segmentation fault求助
C语言动态数组添加函数指针后触发Segmentation Fault的原因与修复
问题背景
实现C语言动态数组(vector)时,原有代码运行正常,在结构体中新增函数指针int (*findEle)(vector*, int)并初始化指向实现函数后,运行触发Segmentation Fault。gdb调试信息显示崩溃发生在initializeVector()函数的v->findEle = findEle;行,访问v->findEle时提示无法访问地址0x620000。
完整问题代码
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef int BOOL; #define TRUE 1 #define FALSE 0 typedef struct Vector vector; struct Vector { int currCapacity; int currSize; int *items; // TODO: Try to add another int field, will cause seg fault int (*size)(vector*); int (*capacity)(vector*); BOOL (*is_empty)(vector*); void *(*at)(vector*, int); void (*push)(vector*, int); void (*insert)(vector*, int, int); void (*resize)(vector*, size_t); int (*pop)(vector*); void (*removeValue)(vector*, int); void (*delete_ele)(vector*, int); int (*findEle)(vector*, int); }; // Vector Functions int size(vector *v) { return v->currSize; } int capacity(vector *v) { return v->currCapacity; } BOOL is_empty(vector *v) { if(v->currSize==0){ return TRUE; } return FALSE; } void *at(vector *v, int index) { if(index >= v->currSize){return NULL;} return (int*)(v->items+index); } void push(vector *v, int item) { if(v->currSize == v->currCapacity) { v->items = (int*)realloc(v->items, sizeof(int)* (v->currCapacity * 2)); v->currCapacity = v->currCapacity * 2; } *(v->items+v->currSize) = item; v->currSize++; } void insert(vector* v, int index, int item) { printf("Inserting %d at index %d\n", item, index); if(v->currSize == v->currCapacity) { v->items = (int*)realloc(v->items, sizeof(int)* (v->currCapacity * 2)); printf("v->items address: %p\n", v->items); v->currCapacity = v->currCapacity * 2; } int* shift_ptr = v->items+index; memmove(v->items+index+1, v->items+index, sizeof(int)*(v->currSize-index)); *(v->items+index) = item; v->currSize++; } void resize(vector* v, size_t size) { printf("Resizing from %d to %d\n", v->currSize, size); v->items = (int*)realloc(v->items, sizeof(int)* size); } int pop(vector* v) { int last = *(v->items + (v->currSize-1)); v->currSize--; if(v->currSize*4 == v->currCapacity) { v->resize(v, v->currCapacity/2); } return last; } void delete_ele(vector* v, int index) { int *curr_ptr = v->items+index; if(v->currSize*4 == v->currCapacity) { v->resize(v, v->currCapacity/2); } memmove(curr_ptr, curr_ptr+1, sizeof(int)*(v->currSize-(index+1))); v->currSize--; } void removeValue(vector *v, int value) { for(int i=0; i<v->currSize; i++) { int ptr_value = *(v->items+i); printf("%d->%d ", i, ptr_value); if(ptr_value==value) { delete_ele(v, i); --i; } } printf("\n"); } int findEle(vector* v, int value) { for(int i=0; i<v->currSize; i++) { if(*(v->items+i)==value) { return i; } } return -1; } vector *initializeVector() { vector *v; v->currSize = 0; v->currCapacity = 2; v->items = (int*)malloc(sizeof(int) * v->currCapacity); v->size = size; v->capacity = capacity; v->is_empty = is_empty; v->at = at; v->push = push; v->insert = insert; v->pop = pop; v->removeValue = removeValue; v->delete_ele = delete_ele; v->findEle = findEle; return v; } int main() { vector *v = initializeVector(); v->push(v, 8); v->push(v, 25); v->push(v, 25); v->push(v, 12); printf("element 0 :%d\n", *(int*)v->at(v, 0)); printf("element 1 :%d\n", *(int*)v->at(v, 1)); printf("element 2 :%d\n", *(int*)v->at(v, 2)); printf("element 3 :%d\n", *(int*)v->at(v, 3)); v->insert(v, 1, 50); printf("element 0 :%d\n", *(int*)v->at(v, 0)); printf("element 1 :%d\n", *(int*)v->at(v, 1)); printf("element 2 :%d\n", *(int*)v->at(v, 2)); printf("element 3 :%d\n", *(int*)v->at(v, 3)); printf("element 4 :%d\n", *(int*)v->at(v, 4)); //printf("%d\n", v->pop(v)); printf("%d\n", v->findEle(v, 25)); v->removeValue(v, 25); for(int i=0; i<v->currSize; i++) { int ptr_value = *(v->items+i); printf("%d->%d ", i, ptr_value); } free(v->items); return 0; }
核心崩溃原因
initializeVector()函数中,vector *v;仅声明了指针变量,但未为vector结构体本身分配内存,v是一个野指针,指向随机的内存地址。
- 原有结构体较小时,对野指针的成员赋值可能恰好落在程序可访问的内存区域(如栈上的空闲空间),因此未触发崩溃;
- 新增函数指针后,结构体总大小增加,赋值操作越界写入了操作系统未授权的内存区域,直接触发Segmentation Fault。
修复方案
1. 为vector结构体分配内存
修改initializeVector()函数,先调用malloc为结构体本身分配内存,并检查分配是否成功:
vector *initializeVector() { // 为vector结构体分配内存 vector *v = (vector*)malloc(sizeof(vector)); if(v == NULL) { perror("malloc for vector failed"); exit(EXIT_FAILURE); } v->currSize = 0; v->currCapacity = 2; v->items = (int*)malloc(sizeof(int) * v->currCapacity); // 检查items内存分配是否成功 if(v->items == NULL) { perror("malloc for items failed"); free(v); // 已分配的结构体内存要释放 exit(EXIT_FAILURE); } v->size = size; v->capacity = capacity; v->is_empty = is_empty; v->at = at; v->push = push; v->insert = insert; v->pop = pop; v->removeValue = removeValue; v->delete_ele = delete_ele; v->findEle = findEle; return v; }
2. 释放vector结构体内存
在main函数末尾,释放完v->items后,要释放vector结构体本身的内存:
free(v->items); free(v); // 新增该行,避免内存泄漏 return 0;
额外注意事项
- 所有
malloc/realloc调用后必须检查返回值是否为NULL,避免内存分配失败导致后续非法内存访问; - 野指针操作是C语言中常见的崩溃根源,使用指针前务必确保其指向有效内存区域。
内容的提问来源于stack exchange,提问作者code.c.c
相关产品推荐
相关产品推荐

