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

C语言动态结构体数组内存分配出现SEGV错误的排查与修复

修复结构体数组动态分配内存的段错误问题

尝试从命令行传入的文件中读取URL,存入包含URL内容和原文件位置的结构体数组时,运行出现SEGV on unknown address段错误,以下是问题分析和修复方案:

原代码的错误点

  • 数组索引误用:内层循环中urlArray[i].url = malloc(...)的i是外层处理文件的索引,而非当前结构体数组的元素索引,导致访问数组越界。
  • pos字段赋值错误:urlArray->pos = numURLs始终给数组第一个元素的pos赋值,而非当前URL对应的结构体元素。
  • 总元素计数变量作用域错误:numURLs在每次处理新文件时被重置为0,导致realloc计算的内存大小错误,覆盖之前分配的内存或导致越界。
  • 未检查文件打开状态:fopen可能返回NULL(文件不存在/权限不足),直接调用fscanf会触发错误。
  • 未检查内存分配结果:realloc和malloc可能分配失败返回NULL,后续操作会导致段错误。

修复后的代码

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

typedef struct url {
    char *url;  // URL内容
    int pos;    // 在原文件中的位置(从1开始计数)
} URL;

int main(int argc, char *argv[]) {
    // 检查命令行参数
    if (argc < 2) {
        fprintf(stderr, "Usage: %s <file1> <file2> ...\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    URL *urlArray = NULL;
    char urlBuffer[1000];
    // 总URL计数,放在外层循环外,累计所有文件的URL数量
    size_t totalURLs = 0;

    for (int fileIdx = 0; fileIdx < argc - 1; fileIdx++) {
        FILE *fp = fopen(argv[fileIdx + 1], "r");
        // 检查文件是否打开成功
        if (!fp) {
            fprintf(stderr, "Failed to open file: %s\n", argv[fileIdx + 1]);
            // 释放已分配的内存,避免泄漏
            for (size_t i = 0; i < totalURLs; i++) {
                free(urlArray[i].url);
            }
            free(urlArray);
            exit(EXIT_FAILURE);
        }

        // 当前文件内的URL位置计数
        int filePos = 0;
        while (fscanf(fp, "%s", urlBuffer) != EOF) {
            filePos++;
            // 重新分配内存,总数量+1,用临时变量接收避免内存泄漏
            URL *temp = realloc(urlArray, (totalURLs + 1) * sizeof(URL));
            if (!temp) {
                fprintf(stderr, "Realloc failed\n");
                // 释放已分配资源
                for (size_t i = 0; i < totalURLs; i++) {
                    free(urlArray[i].url);
                }
                free(urlArray);
                fclose(fp);
                exit(EXIT_FAILURE);
            }
            urlArray = temp;

            // 为当前URL分配内存
            urlArray[totalURLs].url = malloc(strlen(urlBuffer) + 1);
            if (!urlArray[totalURLs].url) {
                fprintf(stderr, "Malloc failed for URL\n");
                // 释放已分配资源
                for (size_t i = 0; i < totalURLs; i++) {
                    free(urlArray[i].url);
                }
                free(urlArray);
                fclose(fp);
                exit(EXIT_FAILURE);
            }
            strcpy(urlArray[totalURLs].url, urlBuffer);
            // 设置当前URL在原文件中的位置
            urlArray[totalURLs].pos = filePos;

            totalURLs++;
        }

        fclose(fp);
    }

    // 可选:打印测试结果
    for (size_t i = 0; i < totalURLs; i++) {
        printf("URL: %s, Position: %d\n", urlArray[i].url, urlArray[i].pos);
    }

    // 释放所有分配的内存
    for (size_t i = 0; i < totalURLs; i++) {
        free(urlArray[i].url);
    }
    free(urlArray);

    return EXIT_SUCCESS;
}

关键修复说明

  • 调整计数变量作用域:将totalURLs放在外层循环外,累计所有文件的URL总数,确保realloc计算的内存大小正确。
  • 修正数组索引:使用totalURLs作为当前结构体数组的元素索引,确保操作的是刚分配的内存位置。
  • 正确设置pos字段:每个URL的pos对应其在当前文件中的位置(从1开始计数),通过filePos变量跟踪。
  • 增加错误检查:检查文件打开、realloc和malloc的返回值,出错时释放已分配的内存,避免内存泄漏并优雅退出。
  • 内存安全处理:用临时变量接收realloc的返回值,避免原指针丢失导致内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 20:50:35