内存对齐

内存对齐还是需要重视的——XMMATRIX 为例

和自甴很熟 提交于 2019-12-09 19:36:41
最近研究 D3D,搜了一个教材跟着学: http://www.rastertek.com/dx11s2tut04.html 用 x64 的配置运行,完美,过了几天需要用 x86 测试,结果一运行,程序崩溃…… 赶紧排查问题,x64 的 Debug、Release 都是可以的,而 x86 则是 Debug 可以,Release 才会崩。 开发环境是 VS2015,编译时曾经遇到一些错误和警告,是 UMU 自己消灭掉了,最后有一类警告应该是关键: warning C4316: 'SystemClass': object allocated on the heap may not be aligned 16 原因是 XMMATRIX 需要 16 字节对齐,但代码的作者把它塞在几个类里,然后去 new 这些类了…… 尝试把这些类从 heap 改为 stack,问题解决! 八哥太多,不能轻易放任警告! 来源: oschina 链接: https://my.oschina.net/u/725292/blog/1553339

对内存对齐模式的理解

社会主义新天地 提交于 2019-12-09 13:44:52
对内存对齐模式的理解 在学习结构体的时候,我们在定义一个结构体,例如, typedef struct STI { char id[9]; char name[15]; int age; char sex; int score; }STI; STI stu = {“123456”, “zhangke”, 18, 0, 90}; 经过上机验证会发现,sizeof(STI)的结果是36,而并不是33.而之所以会多出3个字节的原因就在于,内存对齐模式! 其实,内存对齐模式就是说,在内存中的所有变量的字节分配是按照1B,2B,4B或8B的倍数来分配存储空间的,而内存对齐的需要是基于“内存的页式管理”。内存的页式管理就是以页面的方式实现对内存的分配与回收,理解页式管理模式之前,需要了解“连续存储空间分配管理”模式。 “连续存储空间分配管理模式”,简单的说就是,操作系统基于“已分配空间表”和“未分配空间表”对内存空间的分配管理。我们可以通过C语言中的malloc函数和free函数来理解,malloc函数申请空间,需要提供申请的空间的大小,函数返回值是一个地址值,也就是说,我们不需要关心申请的空间的具体位置,只要提供大小即可,由操作系统为我们分配(空间足够就分配),而free函数需要我们提供首地址,不需要提供大小,因为操作系统会根据首地址在“已分配空间表”中就可以找到其对应的位置以及所占空间大小

内存对齐

…衆ロ難τιáo~ 提交于 2019-12-08 11:10:30
首先在C语言中, 结构体占用的是一片连续的内存空间 对齐原因 大部分的参考资料都是如是说的:   1、 平台原因(移植原因): 不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。   2、 性能原因: 数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。 以前对于内存对齐的计算理解错了,今天看见一个视频幡然醒悟。 以下面的结构体为例: struct stu { char *p;  //4 char arr[2];  //2  → 4+2+2(补)=8 int c;  //4 short d;  //2  → 4+2+2(补)=8 double f;  //8 long g;  //4  → 4+4(下面 float h[2] 中取一个刚好可以凑足 8 个字节)=8 float h[2];  //  4(上面拿走了一个)+4(补)=8 }stu; 内存对齐规则 :以结构体中占用字节数最大的修饰变量的关键字为基准进行对齐。 在 stu 中(32位操作系统):首先占用内存最大的关键字为 double 占 8 个字节。   以此为基准对齐,从头开始看。指针 p 占四个字节,arr 占 1*2 = 2个字节,共 6 个字节,不足 8 位

sizeof和sizeof(string)的问题

删除回忆录丶 提交于 2019-12-07 14:31:11
今天看《程序员面试宝典》一书(为了应付将要到来的微软笔试),看到了sizeof(string)这个问题。在Dev C++上测试的结果是4,很不明白。上网搜了一下,得到如下结果: string strArr1[]={"Trend", "Micro", "Soft"}; sizeof(strArr1)=12 转自: http://apps.hi.baidu.com/share/detail/30398570 关于sizeof(string),今天看那本面试宝典的时候看到这个表达式,有点吃惊,书上写着sizeof(string)=4;当时很纳闷,难道分配4个字节大小的内存给string吗?查阅了相关资料得出结论: string的实现在各库中可能有所不同,但是在同一库中相同一点是,无论你的string里放多长的字符串,它的sizeof()都是固定的,字符串所占的空间是从堆中动态分配的,与sizeof()无关。 sizeof(string)=4可能是最典型的实现之一,不过也有sizeof()为12、32字节的库实现。 但是VC6.0测试后sizeof(string)=16.还是跟编译器有关 #include<iostream> using namespace std; void main(void) { string a[] = {"aaaaa","bbbb","ccc"}; int x =

【内存字节】深入理解sizeof占位内存

核能气质少年 提交于 2019-12-06 20:28:17
###运行代码 让计算机告诉你数据类型站内存情况 //32位系统,地址长度是32位(bit),也就是4Byte 64位系统,地址长度是64位(bit),也就是8Byte //注意 1byte = 8 bit;sizeof byte #import <Foundation/Foundation.h> int main(int argc, char *argv[]) { @autoreleasepool { char a[] = "go swift"; //自动为末尾加上'/0',注意空格也要占字节 char b[14] = "go swift"; char *c = a; char *d = "01234"; int16_t t16; int32_t t32; int64_t t64; NSLog(@"%ld", sizeof(a)); NSLog(@"%ld", sizeof(b)); NSLog(@"%ld", sizeof(c)); NSLog(@"%ld", sizeof(d)); //d是指向字符串常量的字符指针 NSLog(@"%ld", sizeof(*d)); //*d是第一个字符 (所占大小由数据类型决定) NSLog(@"int type: %ld,%ld,%ld,%ld", sizeof(t16),sizeof(t32),sizeof(t64),sizeof(

glPixelStorei 详解 包括像素传输

爱⌒轻易说出口 提交于 2019-12-06 12:04:23
3.glPixelStore 像glPixelStorei(GL_PACK_ALIGNMENT, 1)这样的调用,通常会用于像素传输(PACK/UNPACK)的场合。尤其是导入纹理(glTexImage2D)的时候: C++代码 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexImage2D(,,,, &pixelData); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); 很明显地,它是在改变某个状态量,然后再Restore回来。——为什么是状态?你难道8知道OpenGL就是以状态机不?——什么状态?其实名字已经很直白了,glPixelStore这组函数要改变的是像素的存储格式。 涉及到像素在CPU和GPU上的传输,那就有个 存储格式 的概念。在本地内存中端像素集合是什么格式?传输到GPU时又是什么格式?格式会是一样么?在glTexImage2D这个函数中,包含两个关于颜色格式的参数,一个是纹理(GPU端,也可以说server端)的,一个是像素数据(程序内存上,也就是client端)的,两者是不一定一样的,哪怕一样也无法代表GPU会像内存那样去存储。或者想象一下,从一张硬盘上的图片提取到内存的像素数据,上传给GPU成为一张纹理,这个“纹理”还会是原来的那种RGBARGBA的一个序列完事么?显然不是的

sprintf简介

≯℡__Kan透↙ 提交于 2019-12-06 04:27:10
s p r i n t f 基本用法 输入一段有特点的字符串 #include <cstdio> #include <cstring> using namespace std; int main(){ char a[100]; int pos=0; for(int i=1;i<=10;i++){ pos+=sprintf(a+pos," %d-",i); } a[pos-1]='\n'; printf(a); return 0; } 把整数123打印成一个字符串保存在s中。 sprintf(s,"%d", 123); //产生"123" 可以指定宽度,不足的左边补空格: sprintf(s,"%8d%8d", 123, 4567); //产生:" 123 4567" 当然也可以左对齐: sprintf(s,"%-8d%8d", 123, 4567); //产生:"123 4567" 也可以按照16进制打印: sprintf(s,"%8x", 4567); //小写16进制,宽度占8个位置,右对齐 sprintf(s,"%-8X", 4568); //大写16进制,宽度占8个位置,左对齐 这样,一个整数的16进制字符串就很容易得到,但我们在打印16进制内容时,通常想要一种左边补0的等宽格式,那该怎么做呢?很简单,在表示宽度的数字前面加个0就可以了。 sprintf(s,"%08X",

【Linux】C字节对齐

大兔子大兔子 提交于 2019-12-05 22:18:42
什么是对齐,以及为什么要对齐 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地址访问,这就需要各类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。 对齐的作用和原因 各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能从某些特定地址开始存取。其他平台可能没有这种情况,但是最常见的是如果不按照适合其平台要求对数据存放进行对齐,会在存取效率上带来损失。比如有些平台每次读都是从偶地址开始,如果一个int型(假设为 32 位系统)存放在偶地址开始的地方,那么一个读周期就可以读出,而如果存放在奇地址开始的地方,就可能会需要2个读周期,并对两次读出的结果的高低字节进行拼凑才能得到该int数据。显然在读取效率上下降很多。这也是空间和时间的博弈。 对齐的实现 通常,我们写程序的时候,不需要考虑对齐问题。编译器会替我们选择适合目标平台的对齐策略。当然,我们也可以通过给编译器传递预编译指令而改变对指定数据的对齐方法。 但是,正因为我们一般不需要关心这个问题,所以当编辑器对数据存放做了对齐,而我们不了解的话,常常会对一些问题感到迷惑。最常见的就是struct数据结构的sizeof结果,出乎意料。为此,我们需要对对齐算法所了解。 对齐的算法

C语言 sizeof()用法介绍

爱⌒轻易说出口 提交于 2019-12-05 19:08:20
本文 转自https://www.cnblogs.com/huolong-blog/p/7587711.html 1. 定义 sizeof是一个操作符(operator)。 其作用是返回一个对象或类型所占的内存字节数。 2. 语法 sizeof有三种语法形式: 1) sizeof (object); //sizeof (对象) 2) sizeof object; //sizeof 对象 3) sizeof (type_name); //sizeof (类型) 对象可以是各种类型的变量,以及表达式(一般sizeof不会对表达式进行计算)。 sizeof对对象求内存大小,最终都是转换为对对象的数据类型进行求值。 sizeof (表达式); //值为表达式的最终结果的数据类型的大小 举例: int i; sizeof(int); //值为4 sizeof(i); //值为4,等价于sizeof(int) sizeof i; //值为4 sizeof(2); //值为4,等价于sizeof(int),因为2的类型为int sizeof(2 + 3.14); //值为8,等价于sizeof(double),因为此表达式的结果的类型为double char ary[sizeof(int) * 10]; //OK,编译无误 1. 基本数据类型的sizeof 这里的基本数据类型是指short

C语言中的内存对齐

独自空忆成欢 提交于 2019-12-05 17:27:17
什么是内存对齐 内存对齐”应该是编译器的“管辖范围”。编译器为程序中的每个数据单元安排在适当的位置上。 出现原因( 老生常谈的两句话 ) 平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。 性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。 对齐规则 第一个成员放在偏移量(offset)为0的地方。 以后的每个成员的偏移量: min(#pragma pack()指定的数值,当前成员的大小) 的倍数中。 每个成员对齐后,本身也要对齐,整体的偏移量:min(#pragma pack()指定的数值,结构体最大数据成员的大小)。 关于 #pragma pack 通过 #pragma pack(n) 来设定变量以n字节对齐方式 n字节对齐就是说变量存放的起始地址的偏移量有两种情况 如果n大于等于该变量所占用的字节数,那么偏移量必须满足默认的对齐方式 。 果n小于该变量的类型所占用的字节数,那么偏移量为n的倍数,不用满足默认的对齐方式 。 32位系统默认为4,64位系统默认为8。 举个例子🌰 #include<stdio.h> #pragma pack(4) struct Node{ char a;