一、new或malloc在申请空间时,超出可申请的大小就会分配异常,可申请的大小是多少
通常情况下申请到的空间达不到地址空间上限。内存碎片会影响到我们“一次”申请到的最大内存空间。比如我们有10M空间,申请两次2M,一次1M,一次5M没有问题。但如果我们申请两次2M,一次4M,一次1M,释放4M,那么剩下的空间虽然够5M,但是由于已经不是连续的内存区域也会申请失败。系统也会限制我们的程序申请到的最大内存。Windows下32位程序如果单纯看地址空间能有4G左右的内存可用,不过实际上系统会把其中2G的地址留给内核使用,所以你的程序最大能用2G的内存。除去其他开销,我们能申请到的内存只有1.9G左右。
二、C++循环引用指的是什么,在使用过程当中需要注意什么问题
头文件的循环引用,智能指针的循环引用
我们在工程中应该会经常遇到头文件循环引用的问题,如果不能解耦引用关系,那么就不能通过编译,何为循环引用?其实,就是头文件 1 包含了头文件 2 ,头文件 2 包含了头文件 1
循环引用是指使用多个智能指针share_ptr时,出现了指针直接相互指向,从而形成环的情况,类似于死锁的情况,这种情况下,智能指针往往不能正常调用对象的析构函数,从而造成内存泄漏。
#include <iostream>
using namespace std;
template <typename T>
class Node
{
public:
Node(const T& value)
:_pPre(NULL)
, _pNext(NULL)
, _value(value)
{
cout << "Node()" << endl;
}
~Node()
{
cout << "~Node()" << endl;
cout << "this:" << this << endl;
}
shared_ptr<Node<T>> _pPre;
shared_ptr<Node<T>> _pNext;
T _value;
};
void Funtest()
{
shared_ptr<Node<int>> sp1(new Node<int>(1));
shared_ptr<Node<int>> sp2(new Node<int>(2));
cout << "sp1.use_count:" << sp1.use_count() << endl;
cout << "sp2.use_count:" << sp2.use_count() << endl;
sp1->_pNext = sp2; //sp2的引用+1
sp2->_pPre = sp1; //sp1的引用+1
cout << "sp1.use_count:" << sp1.use_count() << endl;
cout << "sp2.use_count:" << sp2.use_count() << endl;
}
int main()
{
Funtest();
system("pause");
return 0;
}
//输出结果
//Node()
//Node()
//sp1.use_count:1
//sp2.use_count:1
//sp1.use_count:2
//sp2.use_count:2
shared_ptr 只有当引用计数为 0,才会析构释放对象,而上述情况造成了一个僵局,那就是析构对象时先析构 sp2 , 可是由于 sp2 的空间 sp1 还在使用中, 所以 sp2.use_count 减减之后为 1,不释放, sp1 也是相同的道理,由于 sp1 的空间 sp2 还在使用中, 所以 sp1.use_count 减减之后为1,也不释放。 sp1 等着 sp2 先释放, sp2 等着 sp1 先释放, 二者互不相让, 导致最终都没能释放, 造成内存泄漏。
如何解决循环引用问题:
弱指针用于专门解决 shared_ptr 循环引用的问题, weak_ptr 不会修改引用计数即其存在与否并不影响对象的引用计数器。循环引用就是:两个对象互相使用一个 shared_ptr 成员变量指向对方。弱引用并不对对象的内存进行管理,在功能上类似于普通指针,然而一个比较大的区别是,弱引用能检测到所管理的对象是否已经被释放,从而避免访问非法内存。