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

可变参数模板日志函数处理char*空指针崩溃问题求助

解决日志模板处理char*空指针崩溃的问题

你的问题核心在于:std::cout输出char*类型的nullptr时,会触发针对C风格字符串的重载,尝试访问空地址,导致未定义行为(崩溃或程序退出);而void*类型的空指针则会被正常输出为类似0x0的格式,不会出问题。

要在模板层面统一处理,不需要在每个调用点手动判断,可以通过添加类型萃取的辅助函数,对char*/const char*类型单独做空指针检查,其他类型直接转发输出。

修改后的完整代码

#include <iostream>
#include <string>
#include <string_view>
#include <type_traits>

#define LOGGER(...) writet(__FILE__, "::", __PRETTY_FUNCTION__, '[', __LINE__, ']', __VA_ARGS__)

// 辅助函数:处理char*和const char*的空指针情况
template<typename T>
auto log_helper(T&& arg) -> std::enable_if_t<!std::is_same_v<std::decay_t<T>, char*> && !std::is_same_v<std::decay_t<T>, const char*>, T&&> {
    return std::forward<T>(arg);
}

template<typename T>
auto log_helper(T* arg) -> std::enable_if_t<std::is_same_v<std::decay_t<T>, char> || std::is_same_v<std::decay_t<T>, const char>, const char*> {
    return arg ? arg : "(nil)";
}

// 修改后的writet,每个参数先经过log_helper处理
template <typename... Types>
static void writet(Types&&... args)
{
    ((std::cout << log_helper(std::forward<Types>(args)) << ' '), ...) << std::endl << std::flush;
}

int main()
{
    char* test{nullptr};
    const char* test3{nullptr};
    void* test2{nullptr};
    LOGGER(NULL,"dsff",1,1.2,nullptr,test2,test,test3,std::string("hello"));
    LOGGER(std::string_view("hi",2));
    return 0;
}

代码说明

  1. log_helper模板函数:
    • 第一个重载:匹配非char*/const char*的所有类型,直接转发参数,不做额外处理。
    • 第二个重载:专门匹配char*和const char*类型,如果指针为空,返回安全字符串"(nil)";否则返回原指针,避免非法内存访问。
  2. writet函数修改:
    • 输出每个参数前,先调用log_helper做预处理,把空的char*/const char*转换成安全的输出内容,其他类型保持原有输出逻辑。

测试效果

运行后,空的char*/const char*会被输出为(nil),void*类型的空指针仍正常输出0x0,其他数据类型的输出不受影响,完全不需要在调用LOGGER时手动添加空指针判断。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 18:22:33