C++

错误声明vector导致的内存越界

"错误声明vector导致的内存越界"

Posted by Simon on September 7, 2020

“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(101);    //初始化了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);

后一切正常。