“Better code, better life. ”
错误声明vector导致的内存越界
菜鸡程序员小张今天又写bug了,地址访问越界导致的段错误,下面是gdb给的堆栈信息
(gdb) bt
#0 0x00007ffff6542691 in __strlen_sse2_pminub () from /usr/lib64/libc.so.6
#1 0x00007ffff6dc6b19 in length (__s=0xc <Address 0xc out of bounds>) at /gcc-7.3.0/gcc-build-7.3.0/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/char_traits.h:320
不难看出,程序在对内存地址0xc访问时越界了(该地址不在当前程序可访问的内存页表内,有可能是被free掉了)
我的代码大概是这样的:
class Data {
public:
char data[20];
...
}
using DataPtr = std::shared_ptr<Data>;
void fund(){
std::vector<Data> newData(10);
for(int i=0;i<10;++i){
auto item = std::make_shared<Data>();
newData.emplace_back(item);
}
for(const auto&it:newData){
std::cout<<it->data<<std::endl;
}
}
当访问it->data
时报出内存越界的错误。
经过一番折腾才发现是错误声明newData导致的
这里搞混了vector
声明时初始化和reserve
的区别
一般来说,vector有一下几种初始化方式:
(1)不带参数的构造函数初始化
//初始化一个size为0的vector
vector<int> abc;
(2)带参数的构造函数初始化
//初始化size,但每个元素值为默认值
vector<int> abc(10); //初始化了10个默认值为0的元素
//初始化size,并且设置初始值
vector<int> cde(10,1); //初始化了10个值为1的元素
(3)通过可迭代对象初始化
int a[5] = {1,2,3,4,5};
//通过数组a的地址初始化,注意地址是从0到5(左闭右开区间)
vector<int> b(a, a+5);
//insert初始化方式将同类型的迭代器对应的始末区间(左闭右开区间)内的值插入到vector中
vector<int> a(6,6);
vecot<int> b;
//将a[0]~a[2]插入到b中,b.size()由0变为3
b.insert(b.begin(), a.begin(), a.begin() + 3);
所以把
std::vector<Data> newData(10);
改成
std::vector<Data> newData;
newData.reserve(10);
后一切正常。