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

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(&regex, pattern, REG_EXTENDED);
    if (reti) {
        fprintf(stderr, "Could not compile regex\n");
        return NULL;
    }

    // 执行正则,捕获<loc>标签内的URL
    reti = regexec(&regex, 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(&regex);

    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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 22:30:37