第1章

来源:互联网 发布:大数据涂子沛概括 编辑:程序博客网 时间:2024/05/20 12:24

C++里可能出现的内存问题大致有这么几个方面:
1、缓冲区溢出。
2、空悬指针/野指针。
3、重复释放。
4、内存泄漏。
5、不配对的new[]/delete。
6、内存碎片。

解决方法:
1、缓冲区溢出:用std::vector<char>/std::string或自己编写Buffer class来管理缓冲区,自动记住用缓冲区的长度,并通过成员函数而不是裸指针来修改缓冲区。
2、空悬指针/野指针:用shared_ptr/weak_ptr。
3、重复释放:用scoped_ptr,只在对象析构的时候释放一次。
4、内存泄漏:用scoped_ptr,对象析构的时候自动释放内存。
5、不配对的new[]/delete:把new[]统统替换为std::vector/scoped_array。

在这几种错误里边,内存泄漏相对危害性较小,因为它只是借了东西不归还,程序功能在一段时间内还算正常。其他如缓冲区溢出或重复释放等致命错误可能会造成安全性方面的严重后果。

scoped_ptr/shared_ptr/weak_ptr都是值语意,要么是栈上对象,或是其他对象的直接数据成员,或是标准库容器里的元素。几乎不会有下面这种用法:

shared_ptr<Foo>* pFoo = new shared_ptr<Foo>(new Foo);  //Wrong semantic

如果这几种智能指针是对象x的数据成员,而它的模板参数T是个incomplete类型,那么x的析构函数不能是默认的或内联的,必须在.cpp文件里边显式定义,否则会有编译错或运行错。

再论shared_ptr的线程安全
虽然我们借shared_ptr来实现线程安全的对象释放,但是shared_ptr本身不是100%线程安全的。它的引用计数本身是安全且无锁的,但对象的读写则不是,因为shared_ptr有两个数据成员,读写操作不能原子化。shared_ptr的线程安全级别和内建类型、标准库容器、std::string一样,即:
1、一个shared_ptr对象实体可被多个线程同时读取;
2、两个shared_ptr对象实体可以被两个线程用时写入,“析构”算写操作;
3、如果要从多个线程读写同一个shared_ptr对象,那么需要加锁。

请注意,以上是shared_ptr对象本身的线程安全级别,不是它管理的对象的线程安全级别。

析构所在的线程:对象的析构是同步的,当最后一个指向x的shared_ptr离开其作用域的时候,x会同时在同一个线程析构。这个线程不一定是对象诞生的线程。这个特性是把双刃剑:如果对象的析构比较耗时,那么可能会拖慢关键线程的速度(如果最后一个shared_ptr引发的析构发生在关键线程);同时,我们可以用一个单独的线程来专门做析构,通过一个BlockingQueue

0 0
原创粉丝点击