C语言中char与char*赋值警告及段错误问题排查
解决URL存储的类型不匹配与段错误问题
问题根源分析
- 类型不匹配:你在
main中声明的urlStack是char*的数组(char* urlStack[]),但传递给locXMl时用了*urlStack,相当于把数组的第一个空指针传递给了期望接收字符指针的参数。在locXMl中,urlStack[stackIndex]被当作单个字符处理,而你试图赋值char*类型的URL,直接触发"integer from pointer without a cast"警告。 - 空数组访问:
char* urlStack[] = {}是空指针数组,未分配任何存储空间,访问urlStack[stackIndex]会直接引发段错误。 - 局部指针无效:
regSearch返回的是locXMl中局部数组fileData的指针,该数组每次循环都会被覆盖,函数退出后指针会变成野指针。 - 函数返回值错误:
locXMl声明返回char但实际无返回值,属于未定义行为。
修复方案
1. 正确声明和传递URL数组
使用固定大小的指针数组(若能预估URL数量)或动态分配内存,这里以固定大小示例(最多存100个URL)。locXMl参数改为接收char** urlStack(指针的指针,即指针数组地址),同时传递数组最大容量避免越界。
2. 修复regSearch函数
匹配成功时提取<loc>标签内的URL内容而非整行指针,为提取的URL分配堆内存避免局部数组指针失效,匹配失败时返回NULL明确逻辑。
3. 内存管理与错误处理
在locXMl中检查数组是否已满,避免越界;使用完URL后释放内存防止泄漏;添加文件打开、正则编译、curl请求的错误提示。
4. 修正函数返回值
locXMl改为返回实际存储的URL数量,方便后续遍历处理。
完整修正代码
#include <stdio.h> #include <curl/curl.h> #include <string.h> #include <regex.h> #include <stdlib.h> #define MAX_URLS 100 #define MAX_URL_LEN 256 int statusCode(char *addr); char* regSearch(char* regPattern, char* hayStack); int locXMl(char* fileName, char** urlStack, int maxUrls); int main(int argc, char *argv[]) { char* urlStack[MAX_URLS] = {NULL}; // 初始化所有元素为NULL // 检查文件名是否指定 if(argc < 2){ printf("\nMissing file name.\n"); return 1; } // 检查文件是否存在 FILE *file; if((file = fopen(argv[1],"r")) == NULL ) { printf("\nSpecified file does not exist\n"); printf("\n%s\n",argv[1]); return 1; } fclose(file); // 提前关闭,locXMl会重新打开 // 构建URL列表 int urlCount = locXMl(argv[1], urlStack, MAX_URLS); if(urlCount == 0){ printf("No URLs found in the XML file.\n"); return 0; } // 遍历URL并检查状态码 for(int i=0; i<urlCount; i++){ if(urlStack[i]){ int code = statusCode(urlStack[i]); printf("URL: %s -> Status Code: %d\n", urlStack[i], code); free(urlStack[i]); // 释放内存 } } return 0; } int statusCode(char *addr){ CURL *curl; CURLcode res; long response_code = 0; // 初始化curl curl_global_init(CURL_GLOBAL_DEFAULT); // 创建curl句柄 curl = curl_easy_init(); if (curl) { curl_easy_setopt(curl, CURLOPT_URL, addr); curl_easy_setopt(curl, CURLOPT_NOBODY, 1); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); // 处理重定向 res = curl_easy_perform(curl); if(res == CURLE_OK) { curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); } else { fprintf(stderr, "Failed to fetch URL: %s\n", curl_easy_strerror(res)); } curl_easy_cleanup(curl); } // 清理全局curl资源 curl_global_cleanup(); return (int)response_code; } /* 使用正则提取XML中的URL */ char* regSearch(char* regPattern, char* hayStack) { regex_t regex; int reti; regmatch_t match[2]; // 第0个是整个匹配,第1个是捕获组内容 char *pattern = regPattern; char *result = NULL; // 编译正则表达式,开启扩展模式支持捕获组 reti = regcomp(®ex, pattern, REG_EXTENDED); if (reti) { fprintf(stderr, "Could not compile regex\n"); return NULL; } // 执行正则,捕获<loc>标签内的URL reti = regexec(®ex, hayStack, 2, match, 0); if (!reti) { int urlLen = match[1].rm_eo - match[1].rm_so; if(urlLen > 0 && urlLen < MAX_URL_LEN){ result = (char*)malloc(urlLen + 1); if(result){ strncpy(result, hayStack + match[1].rm_so, urlLen); result[urlLen] = '\0'; // 确保字符串结尾 } } } else if (reti != REG_NOMATCH) { fprintf(stderr, "Regex execution failed\n"); } // 释放编译后的正则资源 regfree(®ex); return result; } /* 从XML的loc元素中提取所有URL */ int locXMl(char* fileName, char** urlStack, int maxUrls){ FILE *fptr; fptr = fopen(fileName,"r"); if(!fptr){ fprintf(stderr, "Failed to open file: %s\n", fileName); return 0; } char fileData[MAX_URL_LEN + 30]; // 预留标签长度 int stackIndex = 0; while(fgets(fileData, sizeof(fileData), fptr) && stackIndex < maxUrls) { // 正则添加捕获组,直接提取标签内的URL char* url = regSearch("<loc>([^<]*)</loc>", fileData); if(url){ urlStack[stackIndex] = url; stackIndex++; } } fclose(fptr); return stackIndex; }
关键修改说明
- URL数组处理:
main中声明固定大小的指针数组,传递时直接传数组名(退化为指针的指针),同时传入最大容量防止越界。 - 正则优化:修改正则表达式为
<loc>([^<]*)</loc>,用捕获组直接提取标签内的URL,无需后续处理标签字符串。 - 内存分配:
regSearch为提取的URL分配堆内存,确保指针在locXMl退出后仍有效。 - 错误处理:新增文件打开、正则编译、curl请求的错误提示,提升代码健壮性。
- 内存释放:遍历URL后释放每个URL的内存,避免内存泄漏。
内容的提问来源于stack exchange,提问作者genx
相关产品推荐
相关产品推荐

