数据结构逆向分析-Vector
这个应该是家喻户晓了的东西把,如果说C/C++程序员Vector都不用的话,可能就是一个不太好的程序员。
Vector就是一个STL封装的动态数组,数组大家都知道是通过连续的地址空间来处理的,vector的原理就是如果原来的不够了要扩展,就会开辟一段更大的内存,然后将原来的内容再复制到新的内存里面,释放掉原来的,然后再插入要扩充的。
Vector常用Api:
push_bak() //尾部插入数据
Insert() //插入数据
pop_back() //删除尾部数据
erase() //删除数据
逆向分析:
插入数据
尾部插入
首先是最简单的,一直往里面插入数据
一个只创建了的vector的大小只有16
然后通过内存来查看:
指向的这个地址:
又指回去了。
画个图就是这个样子:
跑第一条插入数据的指令:
MyVector.push_back(100);
内存变成了这样:
这个vector指向的内容还是没有改变。
然后新加入了三个挨着的地址:
目前的情况来看,应该是vector的第二个内容是数组的首地址,然后第三第四个内容是数组的结束地址。
执行:
MyVector.push_back(600);
变成了这样:
比较奇怪的是,如果是后面两个字段表示数组的结束地址,为什么会要两个字段来存放,一个就够了呀,肯定有问题,所以我这里多push几个,且观察这两个字段有没有值不一样的情况出现。
当执行完第五个push_back的时候终于变化了:
查看一下我们这个MyVector的数据结构:
capacity是指不再分配内存的情况下容器的容量,然后size是指容器当前存放了的大小。再对比我们在内存中的情况,那么很有可能就是size就是第三个字段地址减去第二个字段数组首地址,然后除以结构体大小得到的内容,而capacity容器大小就是最后一个字段和第二个字段数组首地址之间的差值。
再往下执行一个看看:
MyVector.push_back(150);
破案了,就是我们想的那样,vector会开辟一段空间,然后往里面加内容,如果超过了容器大小再重新开辟一个。
任意位置插入数据:
红色表示数据改动过,其实就是相当于往后移动,然后再插入进去,就是正常C语言里面会有的动态数组的操作。
删除数据
尾部删除
这里你会发现,用尾删除的办法来说,并没有删除掉这块地址,只是把范围往上移动了。
任意位置删除:
这里也没有删除,只是把后面往前移动了,然后vector的数组大小又缩小:
实质数组大小和容器大小是不一样的
总结