- 浏览: 369693 次
- 性别:
- 来自: 苏州
文章分类
- 全部博客 (335)
- C++ (190)
- 设计模式 (43)
- 数据库技术 (5)
- 网络编程 (11)
- 自动化测试 (6)
- Linux (13)
- OpenSSL (10)
- MS Crypt API (5)
- SCM (2)
- English (4)
- Android (10)
- EMV规范 (1)
- Saturn Platform (0)
- C (10)
- SQL (2)
- ASP.NET (3)
- 英语口语学习 (3)
- 调试工具 (21)
- 编译技术 (5)
- UML (1)
- 项目管理 (5)
- 敏捷开发 (2)
- Http Server (6)
- 代码审查、代码分析 (5)
- 面试基础 (10)
- 重点知识 (16)
- STL (6)
- Efficient C++资料 (8)
- 数据结构和算法 (7)
- 读书笔记 (0)
- 开源项目 (4)
- 多线程 (2)
- Console App (6)
- 个人开源项目 (4)
- IBM DevelopWorks (4)
- Java (16)
- 内存泄漏相关调试和检测 (13)
- 软件测试相关技术 (2)
- C# (11)
- Apple Related (1)
- 软件测试和管理 (2)
- EMV (1)
- Python (1)
- Node.js (6)
- JavaScript (5)
- VUE (1)
- Frontend (1)
- Backend (4)
- RESTful API (3)
- Firebase (3)
最新评论
-
u013189503:
来个密码吧
[C++][Logging] 项目中写日志模块的实现 -
wyf_vc:
来个密码啊!!
[C++][Logging] 项目中写日志模块的实现
转自
http://www.cnblogs.com/dsky/archive/2012/02/07/2340984.html
今天查资料的时候发现 VS 编译器 CL 的一个编译选项可以查看 C++ 类的内存布局,非常有用。使用如下,从开始程序菜单找到 Visual Stdio 2008/2005 Command Prompt,选择 VS 的命令行工具,按如下格式使用:
而使用 –d1reportAllClassLayout 则可以查看源文件中所有类及结构体的内存布局。
其中,classname 为类名,-d1reportSingleClassLayout[classname] 之间没有空格。编写程序测试:
比较奇怪,加上 #include <iostream> 后,测试结构体的时候就会出现很输出,应该是库中的类,看起来真麻烦,所以这里去掉它。
可以看到,VC 默认情况下,结构体内使用字节对齐,char x, 和 int y 之间填充了 3 个字节的空间。默认情况,VC 对结构体内的字节按最大字节对齐,成员变量之间的顺序不同,结构体所占空间也可能不同。
同样可以看到,类 TestClass 中数据成员的按最大数据成员字节对齐,char y 和 double z 之间插入了 7 个字节,double z 和 int x 之间插入了 4 个字节,按 double 型对齐,32 位机器上, sizeof(double) = 8。
其中{vfptr}是虚函数表,可以看到,VC 将虚函数表地址放在了对象的头 4 个字节,接着才是数据成员。虚函数表是一个数组,里面存放的是类中虚函数的地址,可以看到虚函数成员的地址是按照声明的顺序存放的。
可以看到,基类的虚函数存放在虚表的前面,子类中自己声明的虚函数按顺序存放在后面。
可以看到,子类 Derived2 中重写了基类 Base 中的虚函数 f1(),因此 Devried2 的虚表中 f1() 的位置被 Derived2 重写的 f1() 代替,因此便实现了多态。非虚函数地址不存放在虚表中。
可以看到VC中对多重继承的处理,子类 Derived3 的对象中,前 4 个字节存放的是第一个基类的 虚表,然后是第一个基类的数据成员。接着是第 2 个基类的虚表及数据成员。最后才是自己的数据成员。其中,Derived3::$vftable@Base2@: -8, -8 表示第 2 个基类相对于虚表相对于 Derived3 的偏移量 offset。
//测试结构体的字节对齐,以及 #pragma pack(1), offsetof(struct,number) 的用法。
其中,VC对结构体中的数据成员默认按照最大成员对齐,#pragma pack(num) 可以设置对齐字节数,可以为1、2、4、8、16 。也可以使用编译选项 /Zp[1|2|4|8|16] 修改对齐方式,取消修改用#pragma pack(),如果结构体某成员的 sizeof 大于你设置的,则按你的设置来对齐。注意 offsetof 的用法,可以很容易观察结构体的内部结构
还可以使用前面所说的 cl –d1reportSingleClassLayout[classname] test.cpp 编译选项进行相互验证。
http://www.cnblogs.com/dsky/archive/2012/02/07/2340984.html
今天查资料的时候发现 VS 编译器 CL 的一个编译选项可以查看 C++ 类的内存布局,非常有用。使用如下,从开始程序菜单找到 Visual Stdio 2008/2005 Command Prompt,选择 VS 的命令行工具,按如下格式使用:
>cl –d1reportSingleClassLayout[classname] test.cpp
而使用 –d1reportAllClassLayout 则可以查看源文件中所有类及结构体的内存布局。
其中,classname 为类名,-d1reportSingleClassLayout[classname] 之间没有空格。编写程序测试:
比较奇怪,加上 #include <iostream> 后,测试结构体的时候就会出现很输出,应该是库中的类,看起来真麻烦,所以这里去掉它。
//test: >cl Test.cpp /d1reportSingleClassLayout[className] //#include <iostream> //using namespace std; struct S { char x; int y; double z; }; class TestClass { private: char y; double z; int x; }; //base class Base { private: int x; public: virtual void f1(); virtual int g1(); }; //Derived class Derived: public Base { private: char y; public: virtual float f2(); }; //Derived2 class Derived2: public Base { private: double z; public: virtual void f1(); virtual float v2(); int f3(); }; // class Base2 { private: int yy; public: virtual void g2(); }; //多重继承 class Derived3: public Base, public Base2 { private: double zz; public: virtual void g3(); }; // int main() { return 0; }
//测试,1:测试结构体 S:>cl Test.cpp /d1reportSingleClassLayoutS
可以看到,VC 默认情况下,结构体内使用字节对齐,char x, 和 int y 之间填充了 3 个字节的空间。默认情况,VC 对结构体内的字节按最大字节对齐,成员变量之间的顺序不同,结构体所占空间也可能不同。
2. 测度类 TestClass: >cl Test.cpp /d1reportSingleClassLayoutTestClass
同样可以看到,类 TestClass 中数据成员的按最大数据成员字节对齐,char y 和 double z 之间插入了 7 个字节,double z 和 int x 之间插入了 4 个字节,按 double 型对齐,32 位机器上, sizeof(double) = 8。
3.测试有虚函数的类 Base: >cl Test.cpp /d1reportSingleClassLayoutBase
其中{vfptr}是虚函数表,可以看到,VC 将虚函数表地址放在了对象的头 4 个字节,接着才是数据成员。虚函数表是一个数组,里面存放的是类中虚函数的地址,可以看到虚函数成员的地址是按照声明的顺序存放的。
4.测试子类 Derived:>cl Test.cpp /d1reportSingleClassLayoutDerived
可以看到,基类的虚函数存放在虚表的前面,子类中自己声明的虚函数按顺序存放在后面。
5.测试子类Derived2: >cl Test.cpp /d1reportSingleClassLayoutDerived2
可以看到,子类 Derived2 中重写了基类 Base 中的虚函数 f1(),因此 Devried2 的虚表中 f1() 的位置被 Derived2 重写的 f1() 代替,因此便实现了多态。非虚函数地址不存放在虚表中。
6.测试多重继承的类Derived3: >cl Test.cpp /d1reportSingleClassLayoutDerived3
可以看到VC中对多重继承的处理,子类 Derived3 的对象中,前 4 个字节存放的是第一个基类的 虚表,然后是第一个基类的数据成员。接着是第 2 个基类的虚表及数据成员。最后才是自己的数据成员。其中,Derived3::$vftable@Base2@: -8, -8 表示第 2 个基类相对于虚表相对于 Derived3 的偏移量 offset。
//测试结构体的字节对齐,以及 #pragma pack(1), offsetof(struct,number) 的用法。
1: #include <iostream> 2: 3: using namespace std; 4: 5: struct st1 6: { 7: short number; 8: float grade; 9: float grade2; 10: float grade3; 11: char level; 12: }; //20 13: 14: struct st2 15: { 16: char level; 17: short number; 18: float grade; 19: float grade2; 20: float grade3; 21: };//16 22: 23: #pragma pack(1) 24: struct st3 25: { 26: char level; 27: short number; 28: float grade; 29: float grade2; 30: float grade3; 31: }; //15 32: #pragma pack() 33: 34: void TestSizeOf() 35: { 36: cout << __FUNCTION__ << endl; 37: 38: cout << " sizeof(short)= " << sizeof(short) << endl << endl; 39: 40: cout << " sizeof(st1)= " << sizeof (st1) << endl; 41: cout << " offsetof(st1,number) " << offsetof(st1,number) << endl; 42: cout << " offsetof(st1,grade) " << offsetof(st1,grade) << endl; 43: cout << " offsetof(st1,grade2) " << offsetof(st1,grade2) << endl; 44: cout << " offsetof(st1,grade3) " << offsetof(st1,grade3) << endl; 45: cout << " offsetof(st1,level) " << offsetof(st1,level) << endl << endl; 46: 47: cout << " sizeof(st2)= " << sizeof (st2) << endl; 48: cout << " offsetof(st2,level) " << offsetof(st2,level) << endl; 49: cout << " offsetof(st2,number) " << offsetof(st2,number) << endl; 50: cout << " offsetof(st2,grade) " << offsetof(st2,grade) << endl; 51: cout << " offsetof(st2,grade2) " << offsetof(st2,grade2) << endl; 52: cout << " offsetof(st2,grade3) " << offsetof(st2,grade3) << endl << endl; 53: 54: cout << " sizeof(st3)= " << sizeof (st3) << endl; 55: cout << " offsetof(st3,level) " << offsetof(st3,level) << endl; 56: cout << " offsetof(st3,number) " << offsetof(st3,number) << endl; 57: cout << " offsetof(st3,grade) " << offsetof(st3,grade) << endl; 58: cout << " offsetof(st3,grade2) " << offsetof(st3,grade2) << endl; 59: cout << " offsetof(st3,grade3) " << offsetof(st3,grade3) << endl << endl; 60: } 61: int main() 62: { 63: TestSizeOf(); 64: return 0; 65: }
其中,VC对结构体中的数据成员默认按照最大成员对齐,#pragma pack(num) 可以设置对齐字节数,可以为1、2、4、8、16 。也可以使用编译选项 /Zp[1|2|4|8|16] 修改对齐方式,取消修改用#pragma pack(),如果结构体某成员的 sizeof 大于你设置的,则按你的设置来对齐。注意 offsetof 的用法,可以很容易观察结构体的内部结构
还可以使用前面所说的 cl –d1reportSingleClassLayout[classname] test.cpp 编译选项进行相互验证。
发表评论
-
FreeRTOS
2022-03-05 16:31 248Ref https://blog.csdn.net/weix ... -
串口通讯相关
2018-11-02 13:44 410https://bbs.csdn.net/wap/topics ... -
[转]C++验证IP是否可以PING通
2018-10-30 17:54 1325https://www.cnblogs.com/guoyz13 ... -
C++/MFC 換皮膚
2018-10-20 11:05 477https://blog.csdn.net/u01123991 ... -
WinCE 截屏 - C++ 代碼
2018-08-31 09:45 574// this function create a bmp ... -
[轉] android默认debug.keystore的密码
2017-12-12 11:14 1056http://blog.csdn.net/leehong200 ... -
Android NDK搭建環境
2017-11-27 13:25 580https://www.cnblogs.com/ut2016- ... -
8583协议相关
2017-10-17 13:38 5728583相关资料,整理中... -
Java反编译工具 - Java Decompiler
2017-06-21 20:14 475http://jd.benow.ca/ JD-GUI is ... -
JAVA环境变量配置
2017-06-19 13:56 355参考Link http://www.cnblogs.com/x ... -
Java高级应用之JNI
2017-06-19 09:00 600参考link http://www.cnblogs.com/l ... -
Windows7上使用VMWare搭建iPhone开发环境
2017-05-17 08:49 449Windows7上使用VMWare搭建iPhone开发环境 h ... -
C++实现ping功能
2017-04-18 11:21 2154基础知识 ping的过程是向目的IP发送一个type=8的I ... -
OpenSSL 编译环境搭建
2017-03-27 15:01 9061 安裝VS2008到 c:\Program Files (x ... -
最优非对称加密填充(OAEP)
2017-03-25 14:53 1582OpenSSL命令---rsautl http://blog. ... -
[Platform Builder] 设置SVM OS build Env
2016-11-10 11:39 01 copy one OSDesign Project to ... -
[Windows] System Error Codes(GetLastError )0-----5999
2016-10-26 13:28 1880ERROR_SUCCESS 0 (0x0) T ... -
开源Windows驱动程序框架
2016-09-17 21:35 871转自 http://code.csdn.net/news/28 ... -
c/c++代码中执行cmd命令
2016-09-14 14:50 1908转自 http://blog.csdn.net/slixinx ... -
C#使用C++标准DLL实例(包含callback)
2016-09-11 19:44 1085C++编写标准Win32DLL如下 头文件 /***** ...
相关推荐
标题中的“分析c++对象在内存中的布局情况”是指探讨C++编程中对象在内存中的存储方式,包括成员变量的排列、内存对齐原则以及如何通过特定编译器选项(如VS2010的/d1reportSingleClassLayout)来查看这种布局。...
在Windows平台下,使用Microsoft的cl编译器,通过`/d1 reportSingleClassLayoutBase`选项可以查看单个类的布局信息。这个选项会显示类的成员变量在内存中的位置,以及类的总大小。例如,一个名为Base的普通类,包含...
在描述中提到的"/d1reportSingleClassLayout(类名)"和"/d1reportAllClassLayout"是微软Visual Studio编译器的两个开关选项,它们用于报告类的内存布局。"/d1reportSingleClassLayout"会打印出指定类的对象在内存中的...
调试器支持断点、单步执行、数据观察、内存查看等功能,帮助开发者定位和修复程序错误。 **C++标准库和MFC**: VC9提供对C++标准库的支持,包括STL(标准模板库)、智能指针、异常处理等。同时,它还包含了...
4. **经典界面**:对于习惯使用经典开发工具的开发者,VC 6.0的界面布局和操作方式具有怀旧价值,尤其对于初学者来说更易于上手。 ### 核心组件: 1. **编译器(CL)**:负责将源代码转换成可执行文件。尽管其支持...
`cl.exe` 是 Microsoft Visual C++ 的编译器工具,用于将源代码转换为机器码。 - **-OPTIMIZATION- 优化选项**: 如 `/O2` 表示最大速度优化。 - **-LANGUAGE- 语言选项**: 如 `/std:c++17` 指定 C++17 标准。 - **-...
### VC6.0详细使用说明 #### 一、概述 Visual C++ 6.0 (简称VC6.0)是一款由微软开发的经典集成开发环境(IDE),主要用于C/C++程序的编写与调试。该工具在程序员社区中拥有广泛的用户基础,尤其是在学习阶段,很多...
6. **编译和链接**:使用VC的命令行编译器(如`cl.exe`)或者在Visual Studio中直接编译生成的项目。编译过程可能会生成多个库文件,包括`libicudata.lib`、`libicui18n.lib`、`libicuuc.lib`等,这些是ICU的核心...
5.1.4 虚拟内存布局、内存的分工、堆与栈 127 5.1.5 内存的保护属性和存取权限 127 5.1.6 本章API列表 127 5.2 堆管理 129 5.2.1 获取堆句柄、分配与再分配堆 129 5.2.2 获取堆中内存块的大小信息 133 ...
- **GCC编译器基础**:GCC是GNU项目下的标准C/C++编译器,通过简单的命令行选项,如`gcc -c test.c`进行编译,`gcc -o test test.o`进行链接,或`gcc test.c -o test`一次性完成编译和链接。 - **GDB调试器的使用**...
5.1.4 虚拟内存布局、内存的分工、堆与栈 127 5.1.5 内存的保护属性和存取权限 127 5.1.6 本章API列表 127 5.2 堆管理 129 5.2.1 获取堆句柄、分配与再分配堆 129 5.2.2 获取堆中内存块的大小信息 133 ...