最近写个小程序,出现bus error!

int main(void)
{
/**
* char :1个字节
* char*(即指针变量): 4个字节(32位的寻址空间是2^32, 即32个bit,也就是4个字节。同理64位编译器)
* char 和 char*占用字节不一样,所以 声明char *a = "hello,world! my name is cj", 后面会出现bus error, 即内存不对齐,
* 其实在linux报段错误才对! 是因为声明为字符串字面量 后不能 对字符串修改!必须声明称字符数组才能后续修改
*/
char a[] = "hello,world! my name is cj", *cur, *end, *last;
char *sep = "oa";
printf("ori = %s \nsep = %s \n", a, sep); //指针指向字符串
cur = last = a;
end = a + strlen(a) -1; while(cur <= end)
{
//如果不需要删除这个字符
if(!strchr(sep, *cur))
{
*last++ = *cur; //char *a 时,bus error
} cur++;
} *last = '\0'; printf("result = %s \n", a);
return 1;
}

参考深入理解c/c++ 内存对齐

  内存对齐,memory alignment.为了提高程序的性能,数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问(我们将数据读入到寄存器中,并且假设我们的处理器以四个字节为偏移量访问内存(1-4)四个字节,未对齐的数据就会导致内存拼凑);然而,对齐的内存访问仅需要一次访问。

  内存对齐一般讲就是cpu access memory的效率(提高运行速度)和准确性(在一些条件下,如果没有对齐会导致数据不同步现象).依赖cpu,平台和编译器的不同.一些cpu要求较高(这句话说的不准确,但是确实依赖cpu的不同),而有些平台已经优化内存对齐问题,不同编译器的对齐模数不同.总的来说内存对齐属于编译器的问题.

  一般情况下不需要理会内存对齐问题,内存对齐是编译器的事情.但碰到一些问题上还是需要理解这个概念.毕竟c/c++值直接操作内存的语言.需要理解程序在内存中的分布和运行原理.

  总之一句话就是:不要让代码依赖内存对齐.

1.原因:为什么需要内存对齐.

1、平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。

2、性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐(该类型所占字节的整数倍)。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。

2.内存对齐的规则和范例

  讲述内存对齐之前先看下各种类型的大小,和机器字长及编译器有关系:

  所以,int,long int,short int的宽度都可能随编译器而异。但有几条铁定的原则(ANSI/ISO制订的):

  1 sizeof(short int)<=sizeof(int)

  2 sizeof(int)<=sizeof(long int)

  3 short int至少应为16位(2字节)

  4 long int至少应为32位。 unsigned 是无符号的意思。

  例如: 16位编译器

  char :1个字节

  char*(即指针变量): 2个字节

  short int : 2个字节

  int: 2个字节

  unsigned int : 2个字节

  float: 4个字节

  double: 8个字节

  long: 4个字节

  long long: 8个字节

  unsigned long: 4个字节

  32位编译器

  char :1个字节

  char*(即指针变量): 4个字节(32位的寻址空间是2^32, 即32个bit,也就是4个字节。同理64位编译器)

  short int : 2个字节

  int: 4个字节

  unsigned int : 4个字节

  float: 4个字节

  double: 8个字节

  long: 4个字节

  long long: 8个字节

  unsigned long: 4个字节

  64位编译器

  char :1个字节

  char*(即指针变量): 8个字节

  short int : 2个字节

  int: 4个字节

  unsigned int : 4个字节

  float: 4个字节

  double: 8个字节

  long: 8个字节

  long long: 8个字节

  unsigned long: 8个字节

  成员的内存分配规律:从结构体的首地址开始向后依次为每个成员寻找第一个满足条件的首地址x,该条件是x % N = 0,并且整个结构的长度必须为各个成员所使用的对齐参数中最大的那个值的最小整数倍,不够就补空字节。

结构体中所有成员的对齐参数N的最大值称为结构体的对齐参数。

1、数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员的对齐按照#pragma pack指定的数值(或默认值)和这个数据成员类型长度中,比较小的那个进行。在上一个对齐后的地方开始寻找能被当前对齐数值整除的地址.
2、结构(或联合)的整体对齐规则:在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐.主要体现在,最后一个元素对齐后,后面是否填补空字节,如果填补,填补多少.对齐将按照#pragma pack指定的数值(或默认值)和结构(或联合)最大数据成员类型长度中,比较小的那个进行。
3、结合1、2颗推断:当#pragma pack的n值等于或超过所有数据成员类型长度的时候,这个n值的大小将不产生任何效果。

两点注意:数组,嵌套结构体.
数组:
对齐值为:min(数组元素类型,指定对齐长度).但数组中的元素是连续存放,存放时还是按照数组实际的长度.
如char t[9],对齐长度为1,实际占用连续的9byte.然后根据下一个元素的对齐长度决定在下一个元素之前填补多少byte.
嵌套的结构体:
假设
struct A
{
......
struct B b;
......
};
对于B结构体在A中的对齐长度为:min(B结构体的对齐长度,指定的对齐长度).
B结构体的对齐长度为:上述2中结构整体对齐规则中的对齐长度.

例子:
VC++6.0中n 默认是8个字节,可以修改这个设定的对齐参数
也可以采用指令:#pragma   pack(xx)控制.

......其他参考博客

参考地址:http://www.jb51.net/article/45406.htm

C内存对齐问题-bus error!总线错误!其实是 字符串字面量修改问题!的更多相关文章

  1. bus error(总线错误)

    转自 http://blog.csdn.net/todd911/article/details/8813321 在<C专家编程>中提到了总线错误bus error(core dumped) ...

  2. vs2012 函数参数内存对齐引发编译错误

    编译一个游戏库时,遇到个奇怪的问题.一个模板函数,形参是按值传入的.编译时实参是内存对齐过的,无法通过,引发类似下面的错误: error C2719: '_Val': formal parameter ...

  3. c程序中出现segment error 和 bus error 的原因

    在c程序中,经常会遇到段错误(segment error)和总线错误(bus error),这两种问题出现的原因可能如下 段错误: 对一个NULL指针解引用. 访问程序进程以外的内存空间. 实际上,第 ...

  4. [转]bus error与segment error

    在c程序中,经常会遇到段错误(segment error)和总线错误(bus error),这两种问题出现的原因可能如下 段错误: 对一个NULL指针解引用. 访问程序进程以外的内存空间. 实际上,第 ...

  5. C结构体中数据的内存对齐问题

    转自:http://www.cnblogs.com/qwcbeyond/archive/2012/05/08/2490897.html 32位机一般默认4字节对齐(32位机机器字长4字节),64位机一 ...

  6. C++成员变量内存对齐问题,ndk下非对齐的内存访问导致BUS_ADRALN

    同样的代码,在vs下运行正常,在android ndk下却崩溃: signal 7(SIGBUS),code 1 (BUS_ADRALN),fault addr 0xe6b82793 Func(sho ...

  7. [转]C++结构体|类 内存对齐详解

    内存地址对齐,是一种在计算机内存中排列数据(表现为变量的地址).访问数据(表现为CPU读取数据)的一种方式,包含了两种相互独立又相互关联的部分:基本数据对齐和结构体数据对齐 . 为什么需要内存对齐?对 ...

  8. 深入理解c/c++ 内存对齐

    内存对齐,memory alignment.为了提高程序的性能,数据结构(尤其是栈)应该尽可能地在自然边界上对齐.原因在于,为了访问未对齐的内存,处理器需要作两次内存访问:然而,对齐的内存访问仅需要一 ...

  9. 有关于__align(n) ,内存对齐

    __align __align 关键字指示编译器在 n 字节边界上对齐变量. __align 是一个存储类修饰符.它不影响函数的类型. 语法 __align(n) 其中: n 是对齐边界. 对于局部变 ...

随机推荐

  1. selenium自动化之元素定位方法

    在使用selenium webdriver进行元素定位时,有8种基本元素定位方法(注意:并非只有8种,总共来说,有16种). 分别介绍如下: 1.name定位 (注意:必须确保name属性值在当前ht ...

  2. Phaser游戏框架与HTML Dom元素之间的通信交互

    本想按照PHASER的HTML Dom元素官方实例:http://labs.phaser.io/index.html?dir=game%20objects/dom%20element/&q=  ...

  3. 生成dataset的几种方式

    1.常用的方式通过sparksession读取外部文件或者数据生成dataset(这里就不讲了)  注: 生成Row对象的方法提一下:RowFactory.create(x,y,z),取Row中的数据 ...

  4. Ztree结合jbox实现弹窗树结构

    点击添加分类,弹出事项选择框为jbox <a href="#" id="down{{row.id}}" style="display:none& ...

  5. eBay报告:德国或将成为外贸电商热门市场

    [亿邦动力网讯]1月3日消息,日前,跨境电商平台eBay发布公告称,自2014年1月中旬起,卖家在eBay德国 ( eBay.de ).eBay 奥地利 ( eBay.at ) 或eBay瑞士 ( e ...

  6. nginx响应client的处理机制

    nginx与apache的不同响应机制——epoll nginx可以处理上百万级别的并发请求就是源至于异步非阻塞的处理机制,异步非阻塞核心即是epoll nginx内部反向代理

  7. DOM实战

    作者声明:本博客中所写的文章,都是博主自学过程的笔记,参考了很多的学习资料,学习资料和笔记会注明出处,所有的内容都以交流学习为主.有不正确的地方,欢迎批评指正 视频来源:https://www.bil ...

  8. Python3 函数作用域

    一 LEGB 什么是LEGB? L:local 函数内部作用域 E:enclosing 函数内部与内嵌函数之间 G:global 全局作用域 B:build-in 内置作用域 顺序是什么? 跟名字一样 ...

  9. 02慕课网《进击Node.js基础(一)》——CommonJs标准

    是一套规范管理模块 每个js 为一个模块,多个模块作为一个包 node.js和Couchdb是对其的实现: 不同于jQuery 模块:定义.标识.引用(地址/模块名称) 模块类型: 核心模块http ...

  10. 我是IT小小鸟(读后感)

    序 1.兴趣,这本书第一个点讲兴趣,可是在中国填鸭式的教育下,有兴趣也被这种教育给泯灭了. 2.他山之石,可以攻玉.但不可照搬.这点我非常赞同作者的看法.别人东西你拿来,一定要在他的基础上进行创   ...