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

C语言无外部库提取HTML响应超链接时内存问题排查修复

问题诱因
  • 核心问题1:recv 系统调用仅返回接收到的字节数,不会自动在缓冲区末尾追加字符串结束符\0。后续strdup、strtok等字符串处理函数都依赖\0判断字符串边界,未补结束符会导致函数越界访问非法内存,触发段错误。你看到的strlen.S无法打开的提示只是调试时gdb找不到glibc源码的附带现象,本质是代码触发了非法内存访问。
  • 核心问题2:循环逻辑存在空指针访问风险。当strtok遍历完所有片段返回NULL时,你仍会进入判断分支调用strlen(token),给strlen传入空指针直接触发段错误。
  • 次要问题:使用strncpy拷贝前5个字符到token_head后,没有手动追加\0,strcmp会越界读取token_head后面的栈内存,可能导致匹配逻辑异常,也存在内存访问风险。
修复方案

按如下步骤修改代码即可解决问题:

  1. 接收响应时保存recv返回值,手动给缓冲区加结束符:
// 注意定义response_buf时要预留1字节存结束符,比如 char response_buf[4096];
ssize_t recv_len = recv(tcpSocket, response_buf, sizeof(response_buf) - 1, 0);
if(recv_len < 0){
    printf("Error with recv()\n");
}
else {
    response_buf[recv_len] = '\0'; // 手动补字符串结束符
    printf("Successfully receive response\n");
}
  1. 修正循环逻辑,先判断token非空再做后续处理,同时用strncmp替代临时拷贝逻辑简化代码:
char * const dupstr = strdup(response_buf);
char* token = strtok(dupstr, " \n<>");
char last_token[2000];
const char a[] = "a";
const char href[] = "href=";

while (token != NULL) {
    // 安全拷贝token到last_token,避免溢出
    strncpy(last_token, token, sizeof(last_token) - 1);
    last_token[sizeof(last_token) - 1] = '\0';
    
    token = strtok(NULL, " \n<>");
    
    if(strcmp(last_token, a) == 0){
        // 先判断token非空再访问
        if (token == NULL) break;
        size_t len = strlen(token);
        if(len > 5){
            // 直接用strncmp比对,不需要额外拷贝
            if(strncmp(token, href, 5) == 0){
                printf("%s\n", token);
            }
        }
    }
}
// 记得释放strdup申请的堆内存,避免内存泄漏
free(dupstr);
  1. 可选:如果调试时不想再看到strlen.S缺失的提示,可以安装glibc调试符号包,Ubuntu下执行sudo apt install glibc-source glibc-dbg即可,该操作不影响代码运行逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 15:36:04