请求排查STL hash_map输出随编译优化等级变化的原因
问题描述
我正在研究老旧的SimIt-ARM 3.0,它的指令集模拟器(ISS)生成器issgen基于ARMv5指令集架构(ISA),通过Lex规范与Yacc语法定义的内部语言实现。其中的symbol_table类基于已废弃的非标准STL hash_map。
该hash_map行为异常,使用-O0和-O1编译时输出结果不同。以下是最小复现示例(MRE):
#ifdef __GNUC__ #if __GNUC__ < 3 #include <hash_map.h> namespace Sgi { using ::hash_map; using ::hash; }; // inherit globals #else #include <ext/hash_map> #if __GNUC_MINOR__ == 0 && __GNU_C__ == 3 namespace Sgi = std; // GCC 3.0 #else namespace Sgi = ::__gnu_cxx; // GCC 3.1 and later #endif #endif #endif #include <string> #include <iostream> #include <vector> #include <cstring> struct strEql { bool operator()(const char* sz1, const char* sz2) { return strcmp(sz1,sz2) == 0; } }; typedef Sgi::hash_map<const char *, unsigned int, Sgi::hash<char *>, strEql> hash_map; hash_map hasher; unsigned int idx = 1; void insert(const std::string& key) { hash_map::iterator it = hasher.find(key.c_str()); if (it==hasher.end()) { hasher[key.c_str()] = idx++; } } void print_hasher(void) { for(hash_map::iterator it = hasher.begin(); it != hasher.end(); it++) { std::cout << "fisrt: " << it->first << ", second: " << it->second << std::endl; } } int main(void) { insert("xxx"); insert("yyy"); print_hasher(); }
编译命令及输出:
$ g++ mre.cpp -Wno-deprecated -O0 fisrt: xxx, second: 1 fisrt: yyy, second: 2 $ g++ mre.cpp -Wno-deprecated -O1 fisrt: xxx, second: 1
根本原因分析
核心问题:悬空指针引发未定义行为
insert函数的参数key是std::string类型,调用key.c_str()返回的指针指向该std::string内部的字符数组。当insert函数执行完毕,这个局部的std::string会被销毁,其内部内存也会被释放,但你已经把这个指针存入了hash_map。此时hash_map中存储的是悬空指针,后续对hash_map的所有操作都属于未定义行为。编译优化导致表现差异
-O0模式下,编译器不会主动清理临时变量的内存,悬空指针指向的区域可能还保留着原字符串内容,所以程序能正常输出。-O1模式下,编译器会优化内存回收,悬空指针指向的内容被覆盖或释放,导致hash_map中"yyy"的条目无法被正确识别和输出。
哈希逻辑加剧问题
虽然你用strEql按字符串内容做相等判断,但Sgi::hash<char*>是基于指针地址计算哈希值的。当原std::string被销毁后,指针地址可能被其他内存占用,导致hash_map的哈希桶结构异常,进一步放大了行为的不确定性。
修复建议
- 最稳妥的方案是把hash_map的key类型从
const char*改为std::string,这样hash_map会存储字符串的完整拷贝,彻底避免悬空指针问题,同时无需自定义strEql,直接用标准的哈希和相等逻辑即可。 - 如果必须保留
const char*作为key,要确保存入hash_map的指针指向永久内存(比如全局常量字符串、手动动态分配且不会提前释放的内存)。
内容的提问来源于stack exchange,提问作者pmor
相关产品推荐
相关产品推荐

