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

C语言使用malloc存储字符串出现段错误,寻求故障排查

段错误原因分析与代码修正

核心问题梳理

你的代码存在多处指针使用错误与未定义行为,直接导致了段错误,具体问题如下:

  • 结构体定义错误:原代码中struct product{...}product;是定义了一个名为product的结构体变量,而非类型别名,后续使用时容易混淆类型与变量。
  • allocList函数问题:返回类型声明为struct product但无return语句,触发未定义行为;仅为数组第一个元素的regal分配内存,其余元素的regal均为野指针。
  • isInList函数参数与逻辑错误:参数误用二级指针struct product**,实际应使用指向结构体数组的一级指针struct product*;首次调用时直接访问未初始化的name指针(野指针)调用strcmp,引发段错误。
  • insert函数参数传递与指针访问错误:调用isInList时错误传递参数(将二级指针直接传入、传值而非传地址);访问结构体数组元素时误用二级指针索引,导致指针越界。

修正后的完整代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 使用typedef定义结构体类型别名,简化后续代码
typedef struct product {
    int *regal;
    char *name;
} product;

// 初始化结构体数组,为每个元素的regal分配内存并初始化name为NULL
void allocList(product **list, int alloc) {
    *list = malloc(sizeof(product) * alloc);
    for (int i = 0; i < alloc; i++) {
        (*list)[i].regal = calloc(100, sizeof(int));
        (*list)[i].name = NULL; // 初始化name避免野指针
    }
}

// 检查产品是否已存在于列表中
int isInList(product *list, int listSize, char *item, int *itemIndex) {
    for (int i = 0; i < listSize; i++) {
        // 先判断name是否有效,再比较字符串
        if (list[i].name != NULL && !strcmp(item, list[i].name)) {
            *itemIndex = i;
            return 1;
        }
    }
    return 0;
}

// 插入新产品(不存在则插入)
int insert(product **list, int alloc, int *listSize, char *item, int regalIndex) {
    int itemIndex = 0;
    // 传递正确的结构体数组首地址与列表长度指针
    if (isInList(*list, *listSize, item, &itemIndex)) {
        return 0;
    }

    // 检查数组是否已满,避免越界
    if (*listSize >= alloc) {
        printf("数组已满,无法插入新元素\n");
        return 0;
    }

    // 分配字符串内存并复制,正确访问结构体数组元素
    (*list)[*listSize].name = malloc(strlen(item) + 1);
    strcpy((*list)[*listSize].name, item);
    (*list)[*listSize].regal[0] = regalIndex; // 示例:设置regal索引值

    (*listSize)++;
    return 1;
}

int main() {
    product *list = NULL;
    int listAlloc = 2000;
    int listSize = 0;
    allocList(&list, listAlloc);

    char *str = "abcd";
    char *str1 = "bcd";
    insert(&list, listAlloc, &listSize, str, 1);
    insert(&list, listAlloc, &listSize, str, 1); // 重复插入,返回0
    insert(&list, listAlloc, &listSize, str1, 1);

    // 验证插入结果
    for (int i = 0; i < listSize; i++) {
        printf("产品%d:%s,regal[0]=%d\n", i+1, list[i].name, list[i].regal[0]);
    }

    // 释放所有分配的内存,避免泄漏
    for (int i = 0; i < listAlloc; i++) {
        free(list[i].name);
        free(list[i].regal);
    }
    free(list);

    return 0;
}

关键修正说明

  1. 结构体定义:用typedef创建类型别名product,简化类型声明与使用。
  2. 数组初始化:allocList改为void返回类型,循环为每个结构体元素分配regal内存,并初始化name为NULL,避免后续访问野指针。
  3. 存在性检查:isInList改用一级指针访问结构体数组,先判断name是否有效再调用strcmp,避免非法内存访问。
  4. 插入逻辑:修正参数传递方式,添加数组满员检查,使用(*list)[*listSize]正确访问结构体数组的目标元素。
  5. 内存管理:添加完整的内存释放代码,避免内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 15:25:32