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

使用哈希字符串搭配switch-case触发段错误的排查求助

CLI段错误问题排查与修复

我正在开发一款CLI命令行工具,目前需求尚未明确。注意:在使用字符串映射搭配switch-case执行命令后,程序开始出现段错误,但编译阶段无任何错误。运行时通过printf打印argc和argv信息后发现,错误可能在任意位置触发。

代码文件 codeycat.cpp

#include <map>
#include <iostream>

using namespace std;

static enum Functions {
    undef,
    comm_test,
    comm_commands
} functions;

static map<string, Functions> mapStringValues;

static void Initialize();

bool samestr(const char *svar, const char *str)
{
    if (strcmp(svar, str) == 0)
    {
        return true;
    }
    else
    {
        return false;
    }
}

string construct_version(int major, int minor, int patch)
{
    string strmajor = to_string(major);
    string strminor = to_string(minor);
    string strpatch = to_string(patch);

    string version = strmajor + "." + strminor + "." + strpatch;

    return version;
}

int test(string command)
{
    int code = system(command.c_str());
    return code;
}

void commands()
{
    printf("(test, commands)\n");
}

int main(int argc, char *argv[])
{
    string doc = "Usage: codeycat [options...] [function] [args...]\n"
                 "Options:\n"
                 "\t--help -h: Show this message and exit\n"
                 "\t--version -v: Show version and exit\n";

    string version = construct_version(1, 0, 0);

    printf("arg count: %d, args: %s %s %s", argc, argv[0], argv[1], argv[2]);

    if (argc < 2)
    {
        printf("%s", doc.c_str());

        return 1;
    }

    const char command[PATH_MAX] = {*argv[2]};

    switch (mapStringValues[command])
    {
    case undef:
        printf("Command not found: %s", command);

    case comm_test:
        test(argv[3]);

    case comm_commands:
        cout << "Hello" << endl;
        // commands();
    }

    return 0;
}

void Initialize()
{
    mapStringValues["undef"] = undef;
    mapStringValues["test"] = comm_test;
    mapStringValues["commands"] = comm_commands;
}

运行结果

执行./codeycat返回错误码1,但携带--help、--version、-h、-v等选项或执行功能时均触发段错误:

./codeycat
arg count: 1, args: ./codeycat (null) COLORTERM=truecolorUsage: codeycat [options...] [function] [args...]
Options:
    --help -h: Show this message and exit
    --version -v: Show version and exit
./codeycat --help
[1]    12372 segmentation fault  ./codeycat --help
./codeycat -h
[1]    12416 segmentation fault  ./codeycat -h
./codeycat --version
[1]    12459 segmentation fault  ./codeycat --version
./codeycat -v
[1]    12501 segmentation fault  ./codeycat -v
./codeycat test 'echo Hello'
[1]    12544 segmentation fault  ./codeycat test 'echo Hello'
./codeycat commands
[1]    12587 segmentation fault  ./codeycat commands

错误原因分析

  1. 未初始化字符串映射:Initialize()函数从未被调用,mapStringValues是空的,访问mapStringValues[command]时会插入默认值,行为未定义,可能触发段错误。
  2. argv越界访问:printf("arg count: %d, args: %s %s %s", argc, argv[0], argv[1], argv[2]);中,当argc < 3时,argv[1]或argv[2]为NULL,直接用printf打印NULL指针会触发段错误。
  3. command变量初始化错误:const char command[PATH_MAX] = {*argv[2]};仅取了argv[2]的第一个字符,而非完整字符串,且未包含PATH_MAX的定义头文件(需包含<limits.h>或<unistd.h>),导致内存操作异常。
  4. switch-case无break语句:所有case分支未加break,会贯穿执行后续分支,导致错误的函数调用。
  5. 选项处理逻辑缺失:未对--help、-h等选项做判断,直接进入命令处理逻辑,导致错误访问argv[2]。
  6. argv[3]访问未做边界检查:调用test(argv[3])时未检查argc >=4,越界访问会触发段错误。

修复后的代码

#include <map>
#include <iostream>
#include <cstring>
#include <limits.h>
#include <unistd.h>

using namespace std;

enum Functions {
    undef,
    comm_test,
    comm_commands
};

static map<string, Functions> mapStringValues;

static void Initialize()
{
    mapStringValues["test"] = comm_test;
    mapStringValues["commands"] = comm_commands;
}

bool samestr(const char *svar, const char *str)
{
    return strcmp(svar, str) == 0;
}

string construct_version(int major, int minor, int patch)
{
    return to_string(major) + "." + to_string(minor) + "." + to_string(patch);
}

int test(const string& command)
{
    return system(command.c_str());
}

void commands()
{
    printf("Available commands: (test, commands)\n");
}

int main(int argc, char *argv[])
{
    Initialize(); // 初始化映射表

    const string doc = "Usage: codeycat [options...] [function] [args...]\n"
                       "Options:\n"
                       "\t--help, -h: Show this message and exit\n"
                       "\t--version, -v: Show version and exit\n";

    const string version = construct_version(1, 0, 0);

    // 安全打印argv信息
    printf("arg count: %d, args: ", argc);
    for (int i = 0; i < argc; ++i) {
        printf("%s ", argv[i]);
    }
    printf("\n");

    // 处理选项
    if (argc >= 2) {
        if (samestr(argv[1], "--help") || samestr(argv[1], "-h")) {
            printf("%s", doc.c_str());
            return 0;
        }
        if (samestr(argv[1], "--version") || samestr(argv[1], "-v")) {
            printf("codeycat version %s\n", version.c_str());
            return 0;
        }
    }

    // 检查命令参数
    if (argc < 2) {
        printf("%s", doc.c_str());
        return 1;
    }

    const string command = argv[1];
    auto it = mapStringValues.find(command);
    if (it == mapStringValues.end()) {
        printf("Command not found: %s\n", command.c_str());
        printf("%s", doc.c_str());
        return 1;
    }

    switch (it->second) {
        case comm_test:
            if (argc >= 3) {
                test(argv[2]);
            } else {
                printf("Error: test command requires an argument\n");
            }
            break;
        case comm_commands:
            commands();
            break;
        case undef:
            printf("Command not found: %s\n", command.c_str());
            break;
    }

    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 02:10:25