[工作积累] GCC 4.6 new[] operator内存对齐的BUG
对于用户没有定义dctor(包括其所有成员)的类来说, new CLASS[n] 可能会直接请求sizeof(CLASS)*n的空间.
而带有dctor的 类, 因为delete[]的时候要逐个调用析构函数, 要保证调用n次析构.
C++标准没有指定如何具体处理这种情况. 而对于很多数编译器来说, 是在请求的内存前面, 保存对象的个数n(放在其头部).
| sizeof(int) | sizeof(CLASS) | ... | |||
| n | Object[0] | Object[1] | Object[2] | ... | Object[n-1] |
on new[]:
1.call CLASS::operator new[], or ::operator new[] ( n*sizeof(CLASS) + sizeof(int) ) to allocate memory
2.write number n to first memory address
3.offset base in sizeof(int), to locate array base(beginning)
4.call ctor for all objects
on delete[] (ptr)
1.real base: offset ptr in -sizeof(int)
2.read the array element count 'n' in real memory base
3.for each object in array ptr, call dctor for 'n' times
4.call CLASS::operator delete[] , or ::operator delete[] (real base) to free memory
基本原理就是上面这样. 对于处理algined的数据, 编译器需要做额外处理:
1. 要求CLASS::operator new[] 分配出的内存已经是对齐的, 编译器假定它分配的是对齐的内存, 也就是说, 用户实现的CLASS::operator new[] , 需要使用对齐分配.
struct __declspec(align()) Test
{
...
void* operator new[](size_t bytes)
{
return _aligned_malloc(bytes, 16);
}
};
2.sizeof(CLASS) 是对齐后的值, 否则无法保证array中后续所有元素都是对齐的.
3.在上面的基础上, 编译器请求的内存大小有轻微区别:
请求的内存数量稍微偏多:n*sizeof(CLASS) + sizeof(int) => n* sizeof(CLASS) + aligned( sizeof(int) )
注意上面, 前后的 sizeof(CLASS) 的值是不一样的, 前者没有对齐, 后者是对齐后的, 也就是说加了alignment以后, sizeof()的值不一样.
4.偏移量也需要对齐, 从而保证偏移以后的base address是对齐的: 即offset不再是sizeof(int), 而是aligned(sizeof(int))
这样可以保证最终使用的数组是对齐的.
| aligned( sizeof(int) ) | sizeof(CLASS) : aligned | ... | |||
| n | Object[0] | Object[1] | Object[2] | ... | Object[n-1] |
上面的除了operator new[] 需要用户实现以外, 编译器都会把剩余的工作做完.
经过测试MSVC11和MinGW GCC 4.8 都是没有问题的.
但是在android的GCC4.6上是有bug的, offset忽略了对齐的问题, 使用了固定偏移量8. 解决方y法是hack, 在operator new[]/delete[]里面手动处理offest.
[工作积累] GCC 4.6 new[] operator内存对齐的BUG的更多相关文章
- Windows+GCC下内存对齐的常见问题
结构/类对齐的声明方式 gcc和windows对于modifier/attribute的支持其实是差不多的.比如在gcc的例子中,内存对齐要写成: class X { //... } __attrib ...
- struct内存对齐1:gcc与VC的差别
struct内存对齐:gcc与VC的差别 内存对齐是编译器为了便于CPU快速访问而采用的一项技术,对于不同的编译器有不同的处理方法. Win32平台下的微软VC编译器在默认情况下采用如下的对齐规则: ...
- GNU C - 关于8086的内存访问机制以及内存对齐(memory alignment)
一.为什么需要内存对齐? 无论做什么事情,我都习惯性的问自己:为什么我要去做这件事情? 是啊,这可能也是个大家都会去想的问题, 因为我们都不能稀里糊涂的或者.那为什么需要内存对齐呢?这要从cpu的内存 ...
- 重磅硬核 | 一文聊透对象在 JVM 中的内存布局,以及内存对齐和压缩指针的原理及应用
欢迎关注公众号:bin的技术小屋 大家好,我是bin,又到了每周我们见面的时刻了,我的公众号在1月10号那天发布了第一篇文章<从内核角度看IO模型的演变>,在这篇文章中我们通过图解的方式以 ...
- 虚函数列表: 取出方法 // 虚函数工作原理和(虚)继承类的内存占用大小计算 32位机器上 sizeof(void *) // 4byte
#include <iostream> using namespace std; class A { public: A(){} virtual void geta(){ cout < ...
- C/C++: C++位域和内存对齐问题
1. 位域: 1. 在C中,位域可以写成这样(注:位域的数据类型一律用无符号的,纪律性). struct bitmap { unsigned a : ; unsigned b : ; unsigned ...
- C结构体中数据的内存对齐问题
转自:http://www.cnblogs.com/qwcbeyond/archive/2012/05/08/2490897.html 32位机一般默认4字节对齐(32位机机器字长4字节),64位机一 ...
- C语言 结构体的内存对齐问题与位域
http://blog.csdn.net/xing_hao/article/details/6678048 一.内存对齐 许多计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的首地 ...
- c++中类对象的内存对齐
很多C++书籍中都介绍过,一个Class对象需要占用多大的内存空间.最权威的结论是: *非静态成员变量总合.(not static) *加上编译器为了CPU计算,作出的数据对齐处理.(c语言中面试中经 ...
随机推荐
- 【译】Spark官方文档——Spark Configuration(Spark配置)
注重版权,尊重他人劳动 转帖注明原文地址:http://www.cnblogs.com/vincent-hv/p/3316502.html Spark主要提供三种位置配置系统: 环境变量:用来启动 ...
- Kafka入门学习随记(二)
====Kafka消费者模型 参考博客:http://www.tuicool.com/articles/fI7J3m --分区消费模型 分区消费架构图 图中kafka集群有两台服务器(Server), ...
- STM32F0xx_SPI读写(Flash)配置详细过程
Ⅰ.概述 关于SPI(Serial Peripheral Interface)串行外设接口可以说是单片机或者嵌入式软件开发人员必须掌握的一项通信方式,就是你在面试相关工作的时候都可能会问及这个问题.在 ...
- opengl基础学习专题 (二) 点直线和多边形
题外话 随着学习的增长,越来越觉得自己很水.关于上一篇博文中推荐用一个 学习opengl的 基于VS2015的 simplec框架.存在 一些问题. 1.这个框架基于VS 的Debug 模式下,没有考 ...
- 内核堆分配函数brk()源码分析
Evernote公开链接:http://www.evernote.com/shard/s133/sh/5b8d3b26-0e53-4c61-aa43-66f6e87bbcb7/a44096dd557f ...
- Oracle表结构转换SqlSERVER表结构 脚本
在审计工作中,有时需要将Oracle的表结构修改后再SqlSERVER中创建表结构,然后将数据导入到SqlSERVER中,在修改表结构的过程中方法狠多.手工修改,最蠢的方法,或者用工具UE批量修改,还 ...
- libevent I/O示例
I/O示例使用一个windows平台上服务器/客户端的例子来演示.由于为了减少代码篇幅等各种由于本人懒而产生的原因,以下代码没有做错误处理以及有些小问题,但是我想应该不影响演示,大家多包涵. 服务器代 ...
- Swift 中使用Nimble 库进行单元测试
Nimble 从字面上看是 敏捷,灵活 的意思.Nimble 是一个库,一个 断言库.这个库一般用于单元测试.Xcode 6 为我们集成了 XCTest 单元测试库.在正式介绍 Nimble 之前,我 ...
- Thread系列——Thread.Sleep(0)
转载自:http://www.cnblogs.com/ATually/archive/2010/10/21/1857261.html 线程这一概念,可以理解成进程中的一个小单元.这个单元是一个独立的执 ...
- 零基础学习Linux(一)环境搭建
从本文开始我会为大家介绍一下linux环境下详细的集群环境安装.配置.部署到实例演示的整个过程.在此过程中会给大家详细介绍一下Linux的操作技巧和一些工具的使用.今天开始第一步——环境搭建. 第一步 ...