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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 00:20:16