C++继承singleton模板类使用std::unordered_map触发访问违规求助
问题根因分析
核心触发原因
你实现的singleton模板存在设计缺陷:它不会自动创建单例实例,要求必须先手动实例化一次子类(此处为TestManager)对象,才会在父类构造函数中给静态成员ms_singleton赋值。你直接调用TestManager::Instance()时:
- Debug模式下会直接触发
assert(ms_singleton)断言失败 - Release模式下断言被编译忽略,
ms_singleton为未初始化的野指针/空指针,通过该非法指针访问成员变量test_map时,操作的是非法内存地址,直接触发access violation错误。
注释掉test_map.insert语句后,CreateTest方法内没有访问TestManager的成员变量,野指针问题不会触发内存访问冲突,因此程序看起来运行正常。
其他潜在风险点
- 静态成员未显式初始化:模板类的静态成员需要在类外补充定义
template <typename T> T* singleton<T>::ms_singleton = nullptr;,否则初始值是不确定的随机值。 - 地址计算可移植性极差:用
long类型存储、计算指针偏移,在64位系统下如果long为32位宽,会直接截断64位地址,导致ms_singleton指向错误的内存位置。 - 语法错误:
Test类定义结束后遗漏分号,正式编译会直接失败。 - 线程不安全:多线程场景下创建实例时存在竞态条件风险。
修复方案
替换为标准的线程安全懒汉单例实现,无需手动创建实例即可正常调用:
template <typename T> class singleton { protected: // 构造函数设为protected,禁止外部直接创建实例 singleton() = default; virtual ~singleton() = default; // 禁用拷贝、赋值 singleton(const singleton&) = delete; singleton& operator=(const singleton&) = delete; public: static T& Instance() { // C++11及以后标准保证静态局部变量初始化是线程安全的 static T instance; return instance; } static T* instance_ptr() { return &Instance(); } };
修改后直接调用TestManager::Instance()即可拿到合法的实例,test_map.insert操作不会再触发访问违规。
内容的提问来源于stack exchange,提问作者Arslan Göktürk
相关产品推荐
相关产品推荐

