编译期已知数据的大型unordered_map:栈堆分配问题求助
解决Visual Studio C6262警告:大型unordered_map初始化时栈溢出问题
你遇到的问题根源不是unordered_map本身在栈上,而是初始化用的{...}列表会让编译器在栈上生成一个临时的std::pair数组,这个数组大小55k,超过了VS静态代码分析的栈大小限制(默认16k),所以触发了C6262警告。
下面是几种可行的解决方法:
方法1:分步插入键值对
直接创建空的map,再逐个插入键值对,完全避免栈上生成大临时数组:
// defs.cpp unordered_map<string, string>* Keywords = new unordered_map<string, string>(); Keywords->emplace("keyword1", "value1"); Keywords->emplace("keyword2", "value2"); // ... 依次添加所有键值对
这种方式最直接,缺点是代码会变长,如果键值对很多,可以考虑用脚本生成插入代码。
方法2:将初始化数据放到静态存储区
把键值对数组定义为静态全局变量(放在匿名命名空间避免外部可见),这样数组会存在静态存储区而非栈上,再用这个数组初始化map:
// defs.cpp namespace { // 静态存储区的键值对数组 const std::pair<const std::string, std::string> KeywordList[] = { {"keyword1", "value1"}, {"keyword2", "value2"}, // ... 所有键值对 }; const size_t KeywordCount = std::size(KeywordList); } unordered_map<string, string>* Keywords = new unordered_map<string, string>( std::begin(KeywordList), std::end(KeywordList) );
这种方式既保持了初始化的简洁性,又彻底解决了栈溢出的问题,推荐使用。
为什么原代码会触发警告?
new unordered_map(...)确实把map对象分配到了堆上,但初始化列表{...}的底层实现是编译器生成一个栈上的std::pair数组,再把这个数组的地址传给initializer_list构造函数。这个临时数组的大小超过了VS /analyze:stacksize的阈值,所以被检测出来。
内容的提问来源于stack exchange,提问作者LAZ
相关产品推荐
相关产品推荐

