记C++坑:3.结构体和类对齐补齐
来源:互联网 发布:南通软件开发公司 编辑:程序博客网 时间:2024/06/01 13:21
背景:
项目从旧的编译器(VC6)移植到新编译器(VS2015)。
移植过程中有很多的编译错误连接错误都一一解决之后,运行,发现崩溃,错误为声明一个类类型对象变量时候堆栈错误。导致出现内存问题。因为是移植项目,原来的编译器编译的版本跑起来好好的,所以没太怀疑时代码问题,最开始的思考思路一直集中在是不是使用的lib库有问题,检查项目配置,检查各个库的版本,都没有什么发现,后来再来看代码,发现真的就是代码问题,对同一个类型声明的头文件应用的不同cpp中对这个类使用sizeof,发现得到的结果居然不一样。。
所以导致这个堆栈损坏的问题的原因就是因为两边认为的类型的大小不一致,导致交互的时候内存越界了。
而引起问题的最根本原因时原来的代码中
#pragma pack
的使用不规范。
顺便在这个重温一下使用规则,一般在涉及到需要作为数据传递类型的数据结构定义的时候要指定对齐方式,将定义包含在其中,保证不同模块之间数据交互的正确性。
例如:
#pragma pack(push, 1)typedef tag_S{char m_1;int m_2;double m_3;char m_4[5];};#pragma pack(pop)还有不同的写法:
#pragma pack(1)//...#pragma pack()这种写法的问题在于如果之前指定了一种或多种对齐方式,在这段代码之后,这种/些对齐方式将被取消,并还原成默认对齐方式,所以推荐使用push和pop
在代码中还遇到以下存在bug的写法:
#pragma pack(push, 1)//...#pragma pack(pop, 1)看似pop了,但是在pop的同时又指定了按照1字节对齐,所以是有bug的。
下面来说说为什么不这样写会出问题。
首先,当你写的类型是用在不同的程序间来传递数据的,那么不同bit程序默认对齐方式不一致,就导致了数据交互的bug。
当然,在同一个程序中也可能会出现bug。就比如我遇到的。
上一段简单的代码:
StructDef.h
#pragma oncestruct S{char m_1;int m_2;double m_3;char m_4[5];};UserCpp1.cpp
#pragma pack(push,1)#include "StructDef.h"#pragma pack(pop)int GetS_size_1(){return sizeof(S);}UserCpp2.cpp
#pragma pack(push,4)#include "StructDef.h"#pragma pack(pop)int GetS_size_2(){return sizeof(S);}
当然实际的项目中问题不会暴露的这么明显,当文件量很大,并且依赖嵌套很多的时候,这种问题其实是很难通过看代码发现的。
浪费了两天大好时光,记下来以供反思。
0 0
- 记C++坑:3.结构体和类对齐补齐
- 结构体有字节对齐和字节补齐问题
- C语言对齐、补齐
- c/c++结构体和类字节对齐详解
- C/C++结构体和类中的内存对齐
- 内存对齐与补齐 字节对齐与结构体大小
- C结构体对齐
- C结构体对齐
- C-结构体对齐
- C 结构体对齐
- C/C++内存对齐补齐机制
- 内存的对齐和补齐
- C结构体对齐详解
- C语言结构体对齐
- c 中结构体对齐
- c语言结构体对齐
- c语言结构体对齐
- C语言结构体对齐
- 02、React系列之--FlexBox
- JavaScript与JQuery的AJAX的使用代码
- go语言json格式解析与生成示例
- Android Studio的helloworld遇到的坑
- MapView 地图的基本使用
- 记C++坑:3.结构体和类对齐补齐
- Oracle 日常记录点点
- 关于java泛型的坑,你遇到过吗?
- Linux运维笔记-文档总结-系统日志
- 经典SQL语句大全
- 数字序列全组合(递归)
- Python性能优化的20条建议
- 自定义ProgressStateLayout实现网络请求状态间的相互切换
- C++ 共享内存