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
相关产品推荐
相关产品推荐

