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

使用constexpr initializer_list数组在MSVC崩溃,GCC/Clang正常

MSVC编译constexpr初始化列表数组崩溃问题

问题现象

一段用于单元测试的C++代码,在GCC和Clang下可正常编译运行,但在Win10系统使用MSVC 19.38.33133编译后,无论是否启用AddressSanitizer,运行时都会崩溃。

示例代码

#include <initializer_list>
#include <iostream>
#include <string_view>
#include <vector>

using namespace std::string_view_literals;

constexpr std::initializer_list<std::string_view> data[] {
    {},
    {
        "aa"sv,
        "bb"sv,
    },
    {
        "cc"sv,
        "dd"sv,
        "ee"sv,
    },
};

std::vector<std::string> banHashesDataGenerator(size_t index)
{
    if (index >= std::size(data)) {
        throw std::invalid_argument { "index out of range" };
    }
    std::vector<std::string> result;
    for (auto& item : data[index]) {
        result.emplace_back(std::string { item });
    }
    return result;
}

int main()
{
    for (auto& x : banHashesDataGenerator(1)) {
        std::cout << x << '\n';
    }

    return 0;
}

编译及运行日志

C:\Users\marek r\Downloads>cl /std:c++20 /EHcs bug.cpp /fsanitize=address /Zi
Microsoft (R) C/C++ Optimizing Compiler Version 19.38.33133 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

bug.cpp
Microsoft (R) Incremental Linker Version 14.38.33133.0
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:bug.exe
/InferAsanLibs
/debug
bug.obj

C:\Users\marek r\Downloads>bug.exe
=================================================================
==21384==ERROR: AddressSanitizer: access-violation on unknown address 0x000000000000 (pc 0x7ff62bc718e1 bp 0x000000000000 sp 0x008189cff9a0 T0)
==21384==The signal is caused by a READ memory access.
==21384==Hint: address points to the zero page.
    #0 0x7ff62bc718e0 in std::basic_string<char, struct std::char_traits<char>, class std::allocator<char>>::basic_string<char, struct std::char_traits<char>, class std::allocator<char>><class std::basic_string_view<char, struct std::char_traits<char>>, 0>(class std::basic_string_view<char, struct std::char_traits<char>> const &, class std::allocator<char> const &) (C:\Users\marek r\Downloads\bug.exe+0x1400018e0)
    #1 0x7ff62bc7140d in banHashesDataGenerator(unsigned __int64) (C:\Users\marek r\Downloads\bug.exe+0x14000140d)
    #2 0x7ff62bc715a8 in main (C:\Users\marek r\Downloads\bug.exe+0x1400015a8)
    #3 0x7ff62bcb9bbb in invoke_main D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:78
    #4 0x7ff62bcb9bbb in __scrt_common_main_seh D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
    #5 0x7ffd2b8f7343  (C:\WINDOWS\System32\KERNEL32.DLL+0x180017343)
    #6 0x7ffd2cba26b0  (C:\WINDOWS\SYSTEM32\ntdll.dll+0x1800526b0)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: access-violation (C:\Users\marek r\Downloads\bug.exe+0x1400018e0) in std::basic_string<char, struct std::char_traits<char>, class std::allocator<char>>::basic_string<char, struct std::char_traits<char>, class std::allocator<char>><class std::basic_string_view<char, struct std::char_traits<char>>, 0>(class std::basic_string_view<char, struct std::char_traits<char>> const &, class std::allocator<char> const &)
==21384==ABORTING

C:\Users\marek r\Downloads>cl /std:c++20 /EHcs bug.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.38.33133 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

bug.cpp
Microsoft (R) Incremental Linker Version 14.38.33133.0
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:bug.exe
bug.obj

C:\Users\marek r\Downloads>bug.exe

CRASH

问题分析与解决方案

问题本质

这段代码符合C++标准,崩溃是MSVC的已知Bug:在处理constexpr std::initializer_list<std::string_view>数组时,空初始化列表的元素会被错误地初始化,导致后续遍历访问时出现空指针引用。

保留constexpr的修复方案

以下方案可在保留constexpr测试数据的前提下解决问题:

  1. 替换容器类型:用std::array<std::vector<std::string_view>, N>代替initializer_list数组。std::vector在C++20支持constexpr初始化,MSVC对其处理更可靠:

    #include <array>
    // ...
    constexpr std::array<std::vector<std::string_view>, 3> data{
        std::vector<std::string_view>{},
        std::vector<std::string_view>{"aa"sv, "bb"sv},
        std::vector<std::string_view>{"cc"sv, "dd"sv, "ee"sv}
    };
    
  2. 避免空initializer_list:如果逻辑允许,将空的初始化列表替换为包含一个空string_view的列表,后续遍历可跳过空元素;若必须保留空列表,可显式初始化空initializer_list(部分版本MSVC可能仍存在问题,推荐方案1)。

  3. 升级MSVC版本:该Bug在MSVC的后续版本中已被修复,升级编译器到较新版本可直接解决问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 20:17:01