Struct member in Memory offset calc

If you wrote some struct whatever in C or C++ style.

Please be careful for those in memory bug.

1)结构体的内存变换判断

struct  strA{

int a;

int b;

double c;

};

it was used by some software and give it to users.

after sth happened, strA changed

strA{

int a;

int b;

double c;

long d;

};

how to judge strA now hold "d" or not ?

#ifdef  _WIN64

#define  offsetof(s, m)     (size_t)((ptrdiff_t)&reinterpret_cast<const volatile char&>( (((s*)0)->m) ) )

#else

#define  offsetof(s, m)     (size_t)&reinterpret_cast<const volatile char&>( (((s*)0)->m) )

#endif

2.结构体升级(我指的是从C style,扩展到C++ style)

有人看完上面,可能会发现这个部分没必要细究。但是我今天在软件中发现了个bug,在升级struct到C++ style时候,发现原来可以delete的,现在应为struct 有了虚析构函数后,delete内存crash。

struct StrA{

int a;

int b;

StrA(){memset(this, 0, sizeof(StrA));}//这里错误比较明显发现,我的情况是把它放在我需要set 0的时候做了,结果debug了半天才怀疑是这个问题。

virtual ~StrA();

};

但我们 StrA *p = new StrA();

xxxx

NICE_REMOVE( p);//CRASH.

原因:virtual 析构函数里的vptr这一指针在memset时置零了,这就意味着这个指针不能被使用,而delete p时,触发了这一危险。

改进:1.不要virtual(愚蠢的)。2.不要构造函数(注意我的意思是不要对base struct用memset),同时set 析构函数为纯虚,然后memset操作给子结构体去new和delete,这一既保留了strA的核心功能,有可以避免虚函数表在基类的析构错误问题。

时间: 2024-10-17 02:54:09

Struct member in Memory offset calc的相关文章

Linux Process Virtual Memory

目录 1. 简介 2. 进程虚拟地址空间 3. 内存映射的原理 4. 数据结构 5. 对区域的操作 6. 地址空间 7. 内存映射 8. 反向映射 9.堆的管理 10. 缺页异常的处理 11. 用户空间缺页异常的校正 12. 内核缺页异常 13. 在内核和用户空间之间复制数据 1. 简介 用户层进程的虚拟地址空间是Linux的一个重要抽象,它向每个运行进程提供了同样的系统视图,这使得多个进程可以同时运行,而不会干扰到其他进程内存中的内容,此外,它容许使用各种高级的程序设计技术,如内存映射,学习虚

Data 语意学---Data member的存取效率

<深度探索C++对象模型> 对于data member来说,有两种情况 static data member数据 每一个static data member只有一个实体,存放在程序的data segment之中,无论以何种方式,无论类的继承关系如何复杂,存取路径都是非常直接 Nonstatic data members 直接存放在一个class object之中,是属于一个对象的,是需要一个叫做偏移量的值来索引的. 尤其是虚拟继承,虚拟继承将为"经由base class subobj

struct与union字节大小的终极解释

1.字节对齐的细节和编译器实现相关,但一般而言,如在windows下,就VC而言,满足一下三个准则:1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除:2) 结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding): 即:在默认情况下,VC规定各成员变量存放的起始地址相对于结构的起始地址的偏移量:sizeof(类型)或其倍数3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译

Data Member 的存取

考察以下代码: Point3d origin; origin.x = 0.0; 此例中 x 的存取成本是什么? 答案则是视 x 和 Pointd 而定(别打脸, 我知道这是废话). 具体的呢? 因为 x 可能是个 static member, 也可能是个 nonstiatic member; Point3d 可能是个独立的 class, 也可能是另一个 单一的class 派生而来:甚至可能是从多重继承或虚拟继承而来(请不要小看其他人的代码中的可能性, 你都很有可能不知道 C++ 还能这么写, 有

go语言之行--结构体(struct)详解、链表

一.struct简介 go语言中没有像类的概念,但是可以通过结构体struct实现oop(面向对象编程).struct的成员(也叫属性或字段)可以是任何类型,如普通类型.复合类型.函数.map.interface.struct等,所以我们可以理解为go语言中的“类”. 二.struct详解 struct定义 在定义struct成员时候区分大小写,若首字母大写则该成员为公有成员(对外可见),否则是私有成员(对外不可见). type struct_variable_type struct { mem

struct sk_buff结构体详解

struct sk_buff是linux网络系统中的核心结构体,linux网络中的所有数据包的封装以及解封装都是在这个结构体的基础上进行. struct sk_buff_head  {     struct sk_buff *next;     struct sk_buff *prev;          __u32 qlen;     spinlock_t lock; } struct sk_buff {     struct sk_buff *next;     struct sk_buff

struct socket 结构详解

Socket数据结构网络协议CC++ 用户使用socket系统调用编写应用程序时,通过一个数字来表示一个socket,所有的操作都在该数字上进行,这个数字称为套接字描述符.在系统调用 的实现函数里,这个数字就会被映射成一个表示socket的结构体,该结构体保存了该socket的所有属性和数据.在内核的协议中实现中,关于表示 socket的结构体,是一个比较复杂的东西,下面一一介绍.     struct socket.     这是一个基本的BSD socket,我们调用socket系统调用创建

C++对象模型——Data Member的存取(第三章)

3.3    Data Member的存取 已知下面这段代码: Point3d origin; origin.x = 0.0; x的存取成本是什么? 答案视x和Point3d如何声明而定,x可能是个 static member,也可能是个nonstatic member.Point3d可能是个独立(非派生)的 class,也可能从另一个单一的base class 派生而来;虽然可能性,但它甚至可能是从多重继承或虚拟继承而来.下面数节将依次检验每一种可能性. 先看这样一个问题,如果有两个定义,or

C语言struct内存占用问题 (转)

原文:http://hubingforever.blog.163.com/blog/static/17104057920122256134681/ 作者写的很好,摘抄下来以表尊敬!! 一. ANSI C标准中并没有规定,相邻声明的变量在内存中一定要相邻.为了程序的高效性,内存对齐问题由编译器自行灵活处理,这样导致相邻的变量之间可能会有一些填充字节.对于基本数据类型(比如int,char),他们占用的内存空间在一个确定硬件系统下有个确定的值,所以,接下来我们只是考虑结构体成员内存分配情况.1.1.