将constexpr char[]作为结构体模板参数后用fmt输出为何抛异常?
问题分析:constexpr全局数组作为模板参数触发运行时异常
示例代码
template<const char* str> class MyStruct { public: void Print() { cout << fmt::format("{}", str); } }; constexpr char szTest[] = "hello"; int main() { MyStruct<szTest> info; info.Print(); return 0; }
原因解析
这不是C语法规则限制,**是VS2019(16.11.18)的C20实现Bug**:
- 从标准语法来讲,
constexpr全局数组完全符合const char*类型模板参数的要求:它有静态存储期,地址是合法的常量表达式,不存在语法层面的问题。 - 换成
const修饰数组时,编译器会正常为数组分配静态存储内存,模板参数绑定的指针在运行时指向有效内存,std::string_view(或fmt内部的字符串视图)能正常读取字符串内容计算长度,所以程序运行正常。 - 但用
constexpr修饰时,VS2019的编译器对constexpr数组做了过度优化——可能直接把数组内容嵌入代码而非保留静态存储,或者错误解析了模板参数绑定的指针地址,导致运行时指针指向无效内存,最终触发basic_string_view构造时的内存访问异常。
另外,std::format也出现相同问题,说明问题根源不在fmt库,而是编译器对constexpr数组与模板非类型参数结合的处理逻辑有缺陷。
内容的提问来源于stack exchange,提问作者hchlqlz
相关产品推荐
相关产品推荐

