最近做新产品时,由于产品规格变更,处理协议时发现了部分buf存在容量不足的问题。
问题的原因是在组织XML消息时,我们选用了char buf[]来定义一个固定大小的数组,在新产品上,增加了几个XML节点,刚好超过了数字定义的大小,导致XML消息被截取了,甚至有些API访问会导致内存越界,宕机。
思考一个潜在的问题:大家习惯于复制粘贴,没有思考复制的逻辑存在风险,当几万行代码出现同一个潜在问题时,是多么令人头大。
应对这一问题有两种解决方案,
1、修改定义大小
2、C++的自动扩容
方案一看起来简单省事,修改最小,但下一次问题爆发,再排查一遍,着实浪费时间。
方案二我认为能够使用C++的自动扩容,一劳永逸解决这个问题。
使用C++的自动扩容,大概有人说效率低,内存占用多等等,这里我不跟你杠,你连最基本的服务稳定都保证不了,跟我谈什么效率,可笑。
下面来分享一下C++ string类型的自动扩容知识。
C++的自动扩容的策略其实是先定义一个固定大小的空间,当空间不足时,以原容量2的倍数扩增,把原内容拷贝到新的内存空间,释放旧内存。
有人杠的就是拷贝、释放带来的开销,那你不会在定义时指定一个合适的大小吗?
1、std::string的默认初始容量是多少?每次扩容多少?
答案是string 默认初始容量是15
,每次扩容以原容量2的倍数扩增
有兴趣可以使用下面代码进行测试,我附上我的测试结果(不同编译器可能不一样)
#include <iostream>
using namespace std;
int main()
{
std::string defStr;
cout << "defStr size:" << defStr.size() << ", capacity :" << defStr.capacity() << endl;
defStr = "1234567890123456";
cout << "defStr size:" << defStr.size() << ", capacity :" << defStr.capacity() << endl;
defStr += "1234567890123456";
cout << "defStr size:" << defStr.size() << ", capacity :" << defStr.capacity() << endl;
return 0;
}
$ g++ capacity.cpp
defStr size:0, capacity :15
defStr size:16, capacity :30
defStr size:32, capacity :60
2、vector的扩容机制
先说结论:vector的默认预留容量是0
,使用reserve可以修改
默认预留容量
赋值触发扩容是根据右值容量决定
push_back触发扩容是2的倍数扩容
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> vec;
cout << "vec size:" << vec.size() << ", capacity :" << vec.capacity() << endl;
vec.reserve(5); // 控制预留空间
cout << "vec size:" << vec.size() << ", capacity :" << vec.capacity() << endl;
vec = {1,2,3,4,5,6};
cout << "vec size:" << vec.size() << ", capacity :" << vec.capacity() << endl;
for (int i = 0; i < 10; i++)
{
vec.push_back(i);
cout << "vec size:" << vec.size() << ", capacity :" << vec.capacity() << endl;
}
return 0;
}
输出
vec size:0, capacity :0
vec size:0, capacity :5
vec size:6, capacity :6
vec size:7, capacity :12
vec size:8, capacity :12
vec size:9, capacity :12
vec size:10, capacity :12
vec size:11, capacity :12
vec size:12, capacity :12
vec size:13, capacity :24
vec size:14, capacity :24
vec size:15, capacity :24
vec size:16, capacity :24