vector<T> 和 T[] 内存地址区别

2016-05-05 16:19:14 +08:00
 aigebiu

用 libnetfilter_queue 获得数据包, libtins 操作数据包,放回 netfilter 时出现问题:

vector<uint8_t> vec = pkt.serialize();
nfq_set_verdict(qh, id, NF_ACCEPT, size, &vec[0]);

上面这样,(据我测试)只有长度 135 字节以上的数据包才能成功放回,而这样:

uint8_t arr[MAX_BUFSIZ];
copy(vec.begin(), vec.end(), arr);
nfq_set_verdict(qh, id, NF_ACCEPT, size, arr);

就完全没问题。

为什么呢?&vec[0] 和 arr 的地址有什么区别么?

按理说 vector 也是一段连续内存,应该一样的啊。求解,多谢!

3456 次点击
所在节点    C
38 条回复
mug
2016-05-05 17:23:15 +08:00
vector 的内部不一定是连续的。
Monad
2016-05-05 17:38:28 +08:00
反对楼上 摘自 N3690.pdf
没用过 libnetfilter_queue, 楼主你的问题我猜测是 size 有问题...
araraloren
2016-05-05 17:43:56 +08:00
不要这么用 vector 以及其它模板, C 接口就老老实实使用 C 数据结构。。
kkhaike
2016-05-05 17:58:22 +08:00
我也觉得是 size 有问题,你把他替换成 vec.size()试试
aigebiu
2016-05-05 18:18:47 +08:00
@Monad @kkhaike size=vec.size(); 抱歉忘说了

我之所以问内存区别,是推测问题可能跟 vector 分配内存的方式有关(倍增 capacity )
但 new 一个数组也没问题,和静态开的一样 就想不明白了……
bossfrog
2016-05-05 18:49:22 +08:00
@mug 标准保证连续
boydfd
2016-05-05 19:05:00 +08:00
stl 里面小块内存(比如 128 以下)是通过内存池分配的。大于 128 才会通过全局的 malloc 分配。问题应该就出在这,你结合自己的程序考虑一下看
aigebiu
2016-05-05 19:53:24 +08:00
@boydfd 谢谢!应该是这个原因 vec.reserve() 一下就好了…… 能否具体讲下小块内存的“内存池”?或者相关资料?多谢
Monad
2016-05-05 20:04:41 +08:00
@aigebiu 这种东西对上层来说应该是透明的,不应该是这个影响,除非你依赖了某些分割(比如\0 )之类的,
另外把 const unsigned char* 转成 unsigned char* ,如果传入的参数本身就是 const ,那这是未定义行为,也有可能会影响结果。
如果可以上段完整的 gist ,我编译调一调。
boydfd
2016-05-05 20:13:08 +08:00
@aigebiu stl 源码剖析这本书上有介绍
allenx
2016-05-05 20:26:54 +08:00
vector 内部连续,可以当做起始地址为:&vec[0],长度为 sizeof(T)*vec.size()的一段内存。
aigebiu
2016-05-05 21:06:34 +08:00
@Monad 截出一个片段 https://gist.github.com/isofew/3aa6c0eb716655fa60e53e46ae298d56 我觉得还是 stl 实现的问题
neoblackcap
2016-05-05 21:08:30 +08:00
c++03 开始已经要求 vector 对内部存储要连续了。
neoblackcap
2016-05-05 21:08:46 +08:00
@mug c++03 开始已经要求 vector 对内部存储要连续了。
kkhaike
2016-05-05 21:27:22 +08:00
看了下源码,我觉得原因应该是这个传入的长度一定要是 4 的倍数
```
#define NFA_ALIGNTO 4
#define NFA_ALIGN(len) (((len) + NFA_ALIGNTO - 1) & ~(NFA_ALIGNTO - 1))
```
再加上 @boydfd 所说的 ,小内存是内存池,越界访问出了问题?“成功放回”指的是什么?
反正 vector 一定是内部连续的,这样使用确实没问题。
MCVector
2016-05-05 21:28:00 +08:00
std::vector 表示这个锅我不背
aigebiu
2016-05-05 22:03:01 +08:00
@kkhaike 成功将修改后的包放回 netfilter 然后走 routing->forward->postrouting->网卡 出去
现在只是 verdict 传回去了,包的内容没传过去,还是原来的包,走 routing->input->用户进程 这条路了。
4 字节的包一样不行。
ryd994
2016-05-05 22:28:38 +08:00
uint8_t * arr =malloc(size*8);
copy(vec.begin(), vec.end(), arr);
nfq_set_verdict(qh, id, NF_ACCEPT, size, arr);

这样会怎样?
aigebiu
2016-05-05 22:46:25 +08:00
@ryd994 成功放回
colatin
2016-05-06 00:09:10 +08:00
依稀记得 1byte vector 有优化,内部并不是 uint8_t []方式分配内存的

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/276547

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX