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

C语言两次调用getChar函数出现Segmentation Fault问题求助

段错误原因及修复方案

问题根源

段错误的核心原因是strtok函数的特性导致的:

  • 修改原字符串:strtok会将分割位置的字符替换为'\0',第一次调用getChar后,输入字符串已被修改为"11111\0&\011111"的形式。
  • 全局状态留存:strtok内部维护着上次分割的全局状态,第二次调用getChar时,执行strtok(a, " ")会重新从字符串开头分割,拿到第一个token("11111"),接着调用strtok(NULL, " ")时,已无有效后续token,p被赋值为NULL,此时访问p[0]属于空指针引用,直接触发段错误。

修复方案

方案1:复制临时字符串处理,避免修改原字符串

修改getChar函数,每次处理前复制原字符串到临时缓冲区,避免修改原字符串,同时防止strtok的全局状态干扰:

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

char getChar(char *a){
    // 复制原字符串到临时内存
    char *temp = strdup(a);
    if (temp == NULL) {
        fprintf(stderr, "内存分配失败\n");
        exit(EXIT_FAILURE);
    }
    
    char *p = strtok(temp," ");
    if (p != NULL) {
        p = strtok(NULL," ");
    }
    
    // 先判断p是否为空,避免空指针访问
    char result = (p != NULL) ? p[0] : '\0';
    free(temp); // 释放临时内存
    return result;
}

同时修正main函数中getline的返回值类型(应为ssize_t),并增加输入失败的判断:

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

char getChar(char *a);

int main(){
    char *str = NULL;
    size_t n = 0;
    ssize_t read_len = getline(&str,&n,stdin);
    if (read_len == -1) {
        fprintf(stderr, "读取输入失败\n");
        return EXIT_FAILURE;
    }
    
    printf("%c\n", getChar(str));
    char operation = getChar(str);
    printf("存储的操作符:%c\n", operation);
    
    free(str);
    return 0;
}

方案2:一次性提取操作符,避免重复调用

如果只需要获取一次中间操作符,直接调用一次getChar并保存结果即可,无需重复调用:

int main(){
    char *str = NULL;
    size_t n = 0;
    ssize_t read_len = getline(&str,&n,stdin);
    if (read_len == -1) {
        fprintf(stderr, "读取输入失败\n");
        return EXIT_FAILURE;
    }
    
    char operation = getChar(str);
    printf("%c\n", operation);
    // 后续直接使用operation变量
    printf("存储的操作符:%c\n", operation);
    
    free(str);
    return 0;
}

方案3:使用线程安全的strtok_r

strtok_r是strtok的线程安全版本,需要手动维护分割状态,不会留存全局状态,但仍会修改原字符串,需配合临时字符串使用:

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

char getChar(char *a){
    char *temp = strdup(a);
    if (temp == NULL) {
        fprintf(stderr, "内存分配失败\n");
        exit(EXIT_FAILURE);
    }
    
    char *saveptr;
    char *p = strtok_r(temp," ", &saveptr);
    if (p != NULL) {
        p = strtok_r(NULL," ", &saveptr);
    }
    
    char result = (p != NULL) ? p[0] : '\0';
    free(temp);
    return result;
}

内容的提问来源于stack exchange,提问作者игорь кочнов

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 13:50:25