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

C++中如何处理可变参数(var_arg)多类型?及空指针解引用问题解决

C++可变参数多类型处理与空指针解引用问题修复

错误日志

10-08 17:26:00.835  5249  5617 D DigestGenerator:  /apex/com.android.runtime/lib/bionic/libc.so!libc.so (strstr+) ()

10-08 17:26:00.835  5249  5617 D DigestGenerator:  XXbase.apk!libtest.so (test_bool(char const*)+) ()

问题代码

bool test_bool(const char *filename) {
    if (strstr(filename, "yes")) {
        return true;
    }
    return false;
}

long *test_long(long number, ...) {
    va_list args;
    va_start(args, number);
    for(int i=0; i<number; ++i) {
        if (test_bool(va_arg(args, const char *))) {
            //do something
            return 0;
        }
    }
    va_end(args);
    //do something
    return 0;
}

test_long(0, 1, "yes", 3);

问题根源

调用test_long时传入了整数、字符串等多种类型参数,但函数内部强制以const char*类型解析所有可变参数。当解析整数1和3时,会把整数数值当作指针地址,该地址大概率是无效的空指针或非法内存,传入strstr后触发空指针解引用错误。

可变参数多类型的正确处理方式

C++中传统C风格可变参数(va_list)本身不携带类型信息,要安全处理多类型参数,可采用以下方案:

  • 显式标记参数类型:
    在可变参数序列中加入类型标识,让函数能根据标识解析对应类型。示例:

    #include <cstdarg>
    #include <cstring>
    
    enum ArgType { INT, STRING };
    
    bool test_bool(const char *filename) {
        if (filename && strstr(filename, "yes")) { // 先判空避免非法访问
            return true;
        }
        return false;
    }
    
    long *test_long(long number, ...) {
        va_list args;
        va_start(args, number);
        for(int i=0; i<number; ++i) {
            ArgType type = static_cast<ArgType>(va_arg(args, int));
            switch(type) {
                case INT: {
                    long val = va_arg(args, long);
                    // 处理整数逻辑
                    break;
                }
                case STRING: {
                    const char* str = va_arg(args, const char*);
                    if (str && test_bool(str)) {
                        // do something
                        va_end(args);
                        return 0;
                    }
                    break;
                }
            }
        }
        va_end(args);
        // do something
        return 0;
    }
    
    // 调用时先传类型标识,再传参数
    test_long(3, STRING, "yes", INT, 1, INT, 3);
    
  • 采用C++11及以上的可变模板:
    利用模板参数包实现类型安全的可变参数处理,无需手动解析类型:

    #include <cstring>
    
    bool test_bool(const char *filename) {
        if (filename && strstr(filename, "yes")) {
            return true;
        }
        return false;
    }
    
    // 递归终止函数
    long* process_args() {
        // 处理完所有参数后的逻辑
        return 0;
    }
    
    // 处理字符串参数
    template<typename... Args>
    long* process_args(const char* str, Args... args) {
        if (test_bool(str)) {
            // do something
            return 0;
        }
        return process_args(args...);
    }
    
    // 处理整数参数
    template<typename... Args>
    long* process_args(long num, Args... args) {
        // 处理整数逻辑
        return process_args(args...);
    }
    
    template<typename... Args>
    long* test_long(Args... args) {
        return process_args(args...);
    }
    
    // 直接传入任意类型参数,模板自动匹配处理
    test_long(0, 1, "yes", 3);
    
  • 使用std::variant或std::any(C++17+):
    将所有可变参数包装为std::variant或std::any,统一传入后再判断类型:

    #include <vector>
    #include <variant>
    #include <cstring>
    
    bool test_bool(const char *filename) {
        if (filename && strstr(filename, "yes")) {
            return true;
        }
        return false;
    }
    
    long* test_long(std::vector<std::variant<long, const char*>> args) {
        for (auto& arg : args) {
            if (std::holds_alternative<const char*>(arg)) {
                const char* str = std::get<const char*>(arg);
                if (test_bool(str)) {
                    // do something
                    return 0;
                }
            } else if (std::holds_alternative<long>(arg)) {
                long num = std::get<long>(arg);
                // 处理整数逻辑
            }
        }
        // do something
        return 0;
    }
    
    // 调用时包装参数
    test_long({0, 1, "yes", 3});
    

当前错误的紧急修复

如果暂时不想重构代码,至少要在test_bool中先判断指针有效性,避免空指针解引用:

bool test_bool(const char *filename) {
    // 先检查指针是否为空
    if (!filename) {
        return false;
    }
    if (strstr(filename, "yes")) {
        return true;
    }
    return false;
}

但这只是治标,根本解决还是要修复可变参数的类型解析逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 09:58:25