今天费了一个下午调试一个诡异的内存崩溃问题(coredump)
基本上可以稳定复现,但会有不同。经分析崩溃栈,发现都是malloc内存时出现了signal 11段错误?
分配内存时崩溃有可能是传入了非法size值,比如说-1或者0什么的,但那种情况下会抛bad alloc异常,或者返回空指针。
起初怀疑是std::string的默认allocator的问题,甚至怀疑是全局变量未初始化导致的问题。。。
但是都不在点子上!
之后确定是堆内存破坏的情况下,祭起“注代码”大法!发现跟Node/v8的HandleScope、Local/Persistent这些没有什么关系。突然眼前一亮,如下的代码模式:
std::vector<std::shared_ptr<T>> V;
V.reserve(N);
V[i] = std::make_shared<T>(...);
x见鬼,大概知道问题出在什么地方了:reserve仅仅分配STL容器所占的空间,但不会为每个元素执行空初始化。之后的V[i]=赋值操作实际上有一个副作用:会对V[i]的老元素执行一个析构操作。
问题是实际的元素类型是std::shared_ptr<T>!换句话说,会执行std::shared_ptr::~shared_ptr析构操作,进而执行delete T操作!考虑到V[i]的内存由于之前的reserve操作,实际上引用的是一块未初始化的内存,所以这潜在地导致对于一个野指针的delete操作,从而导致堆内存破坏。
修改方法:改reserve为resiz