4月4日在写协议分析器中遇到的问题:对类指针的直接赋值中遇到的问题
2012-04-04 17:52
309 查看
做嗅探器需要对抓来的数据包进行协议分析,一般而言可以做个协议栈什么的,这里展示一下今天下午遇到的问题。
我的协议分析思路是这样子的(拿单个报头):
我本来的打算是考虑到每个协议头都有相似的行为,如分析下一个协议名、获得下一个协议的偏移等等,因此写了一个HeaderInterface接口及一个header:
待到使用时,总是会出现段错误,而且其错误并非因数据越界而起,前思后想,终于发现拷贝到的数据有4个字节的偏移,以EtherHeader为例,本当是dstAddr获得content前6个字节,但现在却是从第5个字节考试,前思后想,终于发现是我的设计在作怪,使用了virtual后,类体中会多出一个v_ptr,显然我用的这个版本的G++是将v_ptr放在类体最前面的,这样指针赋值之后,content的前四个字节就成了v_ptr的内容,调用接口中任何一个函数都会实际访问一个不合法的地址,从而引起段错误。
为了实现协议树,我在每个协议头中加入了一个void *next,结果有一个报头中的字段是这样的:
class SomeProtocol{
...
Byte protocol[2];
void *next;
...
};
结果就是这个next指针导致protocol被迫对齐,整个类多占了2个字节,计算头偏移时使用 this + sizeof(SomeProtocol) -sizeof(next),计算出来的结果是不正确的。
而后,为了避免麻烦,采取计算偏移直接用计算好的数值的方法,形如:
IPv4Header *ipv4Header =(IPv4Header *)( ethHeader +14);
但是结果是不正确的,因为这里的14是14个字节,而前面的ethHeader却暗示其计算按照单个ethHeader的大小作为“1”来算,故而计算出错,应对ethHeader先进行一个强制转换,使其以Byte为单位来计算:
IPv4Header *ipv4Header =(IPv4Header *)( (Byte*)ethHeader +14);
计算结果正确。
指针这厮当真不是个好东西,只是我目前掌握的协议分析方法中只有这一个能够很好的解决重复拷贝等问题(嗅探器需要防备较大的网络流量,要尽量减少协议分析在时间及空间上造成的负担),也只好暂且凑合着用了。若哪位仁兄有好办法,也可留言给我,定当重谢。
我的协议分析思路是这样子的(拿单个报头):
class EtherHeader { Byte dstAddr[6]; Byte srcAddr[6]; Byte protocol[2]; }; 假设收到的数据包以数组形式存在 content中,则如此可获得其内容: EtherHeader *ethHeader =(EtherHeader*) content;
我本来的打算是考虑到每个协议头都有相似的行为,如分析下一个协议名、获得下一个协议的偏移等等,因此写了一个HeaderInterface接口及一个header:
class HeaderInterface { virtual string getNextProtocolName() const =0; virtual Header *nextProtocolOffset() const =0; }; class Header :public HeaderInterface{ virtual string getNextProtocolName().... ... };
class EtherHeader:public Header {
...
class PPPoEHeader:public Header {
...
待到使用时,总是会出现段错误,而且其错误并非因数据越界而起,前思后想,终于发现拷贝到的数据有4个字节的偏移,以EtherHeader为例,本当是dstAddr获得content前6个字节,但现在却是从第5个字节考试,前思后想,终于发现是我的设计在作怪,使用了virtual后,类体中会多出一个v_ptr,显然我用的这个版本的G++是将v_ptr放在类体最前面的,这样指针赋值之后,content的前四个字节就成了v_ptr的内容,调用接口中任何一个函数都会实际访问一个不合法的地址,从而引起段错误。
为了实现协议树,我在每个协议头中加入了一个void *next,结果有一个报头中的字段是这样的:
class SomeProtocol{
...
Byte protocol[2];
void *next;
...
};
结果就是这个next指针导致protocol被迫对齐,整个类多占了2个字节,计算头偏移时使用 this + sizeof(SomeProtocol) -sizeof(next),计算出来的结果是不正确的。
而后,为了避免麻烦,采取计算偏移直接用计算好的数值的方法,形如:
IPv4Header *ipv4Header =(IPv4Header *)( ethHeader +14);
但是结果是不正确的,因为这里的14是14个字节,而前面的ethHeader却暗示其计算按照单个ethHeader的大小作为“1”来算,故而计算出错,应对ethHeader先进行一个强制转换,使其以Byte为单位来计算:
IPv4Header *ipv4Header =(IPv4Header *)( (Byte*)ethHeader +14);
计算结果正确。
指针这厮当真不是个好东西,只是我目前掌握的协议分析方法中只有这一个能够很好的解决重复拷贝等问题(嗅探器需要防备较大的网络流量,要尽量减少协议分析在时间及空间上造成的负担),也只好暂且凑合着用了。若哪位仁兄有好办法,也可留言给我,定当重谢。
相关文章推荐
- 【JavaScript基础】在写冒泡排序时遇到的JavaScript基础问题:JavaScript的数据类型和变量赋值时的原理
- [笔试题 2][c/c++]关于指针直接赋值问题
- [笔试题 2][c/c++]关于指针直接赋值问题
- [笔试题 2][c/c++]关于指针直接赋值问题
- 关于 将一个数组赋值给另外一个数组会重置原来数组的指针 的问题
- java界面设计遇到的一些问题,往容器直接添加组建好事getContentPane()
- C中结构体是否能用=运算符直接赋值的问题
- iOS常见问题之NSString直接赋值带来的困惑
- 关于含有指针成员的类的对象之间赋值指针的问题。
- [异常解决] 初玩SAE遇到的小问题——注册&创建项目+MyEclipse装插件直接部署+一个简单的JSP部署实现
- Tablayout设置下划线宽度以及遇到空指针问题。
- 指针属性直接赋值 最好先retain 否则内存释放导致crash
- 不要再直接用字符串常量给字符串指针初始化/赋值了
- ActionBar中添加搜索框( search )及遇到的空指针问题
- 开始学习Hibernate框架遇到的空指针问题
- 子类new出来的实例赋值给父类对象,父类对象调用方法遇到的问题。
- JAVA readLine()时遇到的赋值异常问题
- 指针的传参数与赋值问题
- 函数的指针参数传出时遇到的问题
- 阿里云OSS ueditor 直接上传oss对象存储遇到的问题