Milestone2.exe出现std::bad_alloc未处理异常,请求排查ErrorState类代码问题
排查std::bad_alloc异常的原因
首先,std::bad_alloc异常通常在内存分配请求无法被系统满足时抛出,结合你的ErrorState类代码,主要有以下几个明确的诱因:
1. 传入message()的字符串为nullptr引发未定义行为
你的message()函数直接调用strlen(str)计算字符串长度,但如果调用方传入的str是nullptr,strlen(nullptr)属于未定义行为——它可能返回一个极大的随机数值,随后new char[strlen(str)+1]会尝试分配远超系统可用内存的空间,直接触发std::bad_alloc。
看这段有问题的实现:
void ErrorState::message(const char* str) { this->m_message = new char[strlen(str) + 1]; strcpy(this->m_message, str); }
这里完全没有检查str是否有效,一旦传入空指针就会触发上述问题。
2. 未释放原有内存导致内存泄漏,最终耗尽系统内存
每次调用message()时,你直接为m_message分配新内存,但没有释放之前已经指向的内存块。这会导致内存泄漏:每调用一次message(),就有一块内存无法被回收,随着程序运行,系统可用内存逐渐被耗尽,最终在某次new操作时抛出std::bad_alloc。
举个例子,像这样的调用就会泄漏内存:
ErrorState err; err.message("First error"); err.message("Second error"); // "First error"对应的内存块永远无法被释放
3. 潜在风险:默认拷贝构造/赋值的浅拷贝问题
虽然你注释掉了自定义的拷贝构造和赋值运算符,但C++会自动生成默认版本。默认拷贝构造会执行浅拷贝,也就是两个ErrorState对象的m_message指向同一块内存。当其中一个对象被销毁时,内存会被释放,另一个对象的m_message就变成悬空指针;如果后续对这个悬空指针进行操作(比如再次调用message()),可能引发包括内存分配失败在内的各种未定义行为。
快速修复建议
针对上述问题,你可以这样调整代码:
- 在
message()开头检查输入有效性,并先释放原有内存:
void ErrorState::message(const char* str) { if (str == nullptr) { clear(); return; } // 先释放旧内存,避免泄漏 clear(); this->m_message = new char[strlen(str) + 1]; strcpy(this->m_message, str); }
- 启用已注释的删除声明,明确禁用拷贝构造和赋值运算符,避免浅拷贝风险:
ErrorState(const ErrorState& em) = delete; ErrorState& operator=(const ErrorState& em) = delete;
内容的提问来源于stack exchange,提问作者Rob Perci
相关产品推荐
相关产品推荐

