Chinaunix首页 | 论坛 | 博客
  • 博客访问: 488682
  • 博文数量: 121
  • 博客积分: 4001
  • 博客等级: 上校
  • 技术积分: 1390
  • 用 户 组: 普通用户
  • 注册时间: 2009-03-13 21:48
文章分类

全部博文(121)

文章存档

2011年(4)

2010年(11)

2009年(106)

我的朋友

分类: C/C++

2009-11-24 17:02:34

       此文为原创,转载请注明出处:http://blog.chinaunix.net/u3/93713/showart.php?id=2102742

 

1.        局部变量太大了容易造成堆栈溢出,比如使用很大的数组。

2.        malloc new 之后一定要检查 动态存储区是否申请成功。

3.        free delete 释放动态动态存储区后一定要将相应的指针赋值为NULL,即 p=NULL

4.        数组名是常指针,不能赋值,除非在将数组作为函数参数,这时候数组名退化为指针变量;

5.        中断服务程序ISR应注意的几个问题:1)中断处理程序不能有返回值;2)中断服务程序不能有参数;3)不能有太耗时的操作,比如浮点,或者是长时间延迟,或者是printf函数;4)必须是重入的;

 

 

 

6.        编译器的作用是将C文件转化为汇编文件。

7.        汇编器的作用是将汇编文件转化为二进制指令流*.o文件(目标文件)。

8.        每个目标文件是独立编址的,也就是说每个目标文件的第一个指令都是从相同的地址开始存放的。

 

 

9.        连接器的作用是1)将多个目标文件或者库文件按照各文件中的段进行统一的编址;2)生成一个完整的统一的地址映像;3)嵌入式系统中一般生成一个绝对地址映像;4)在有MMU的系统中可以为每个任务单独分配一个地址空间;

 

 

10.        程序 = 数据结构 + 算法;

数据结构 = 存储器中的变量        (简单变量,结构体,数组,指针等)

算法 = 存储器中的代码            (指向代码的指针就是函数指针)

11.        看看这段代码有什么问题?

char * DoSomeThing(….)

{

        char i[32*1024];                  // 问题1

        memset(i, 0, 32*1024);

       

       

        return i;                          //问题2

}

问题1:临时变量是通过堆栈实现的,太大的临时变量数组会冲掉堆栈

问题2:返回堆栈中的地址是非常危险的,因为函数返回后堆栈自动销毁,这个时候堆栈中的值是不确定的;

12.        看看这段代码有什么问题?

void DoSomething()

{

        int i;

        int j;

        int k;

        memset(&k, 0, 3*sizeof(int));

}

 

这段代码的作用是将三个临时变量清零;但是这段代码有两个假设:

1)    编译器将ijk三个变量通过堆栈表示

2)    压栈顺序是ijk(假设堆栈是满递减堆栈)

3)    如果k在寄存器怎么办,对k的取地址操作将产生data abort

13.        关于临时变量:

1)  不要对临时变量作取地址操作,因为你不知道编译器是否将这个变量映射到了寄存器;

2)  不要返回临时变量地址,或者临时变量的指针,因为堆栈的内容是不确定的(出了这个函数,存放在堆栈里的局部变量就没有意义了);

3)  不要再申请大的临时变量数组,你的临时变量是在堆栈中实现的,你的堆栈有多大呢?、

14.        问题  现在要为一个矩形区域申请一个内存保存这块数据,如果每个pixel占用2bit,如何分配这个内存呢?

答: 应该是char *buffer = mallocx*y + 1);不能是char *buffer = mallocx*y);

15.        看看这段代码有什么问题?

char *DoSomething(…..)

{

        char *p, *q;

       

if ((p = malloc(1024)) == NULL)  return NULL;

if ((q = malloc(2048)) == NULL)  return NULL;

……..

return p;

}

问题在于:如果p申请成功了而q没有申请成功时,应该释放已申请好的p,再返回NULL

16.        关于动态内存:

1)  总是检查动态内存分配是否成功后再引用该指针;

2)  在分配struct空间时总是使用sizeof

3)  分配内存时 宁滥勿缺 (别忘了加1

4)  总是freemalloc函数返回的指针

5)  按照 ansi C标准free函数是没有返回值的;

6)  错误处理时不要忘记其他已分配空间的释放,

17.        程序BUG的定位:

1)  关注接口 (好的软件架构总是基于层次性的架构,通过相对单纯的数据结构和接口函数与外界交互)

BUG的定位首先应该从上层向下层排查,将断点设在上层函数的入口,单步执行跟踪程序的流程,特别关注底层函数是否正确(主要是关注它的返回值是否正确),搜索的方位逐渐缩小,最后定位在一个函数内部。

2)  关注内存的访问越界

C语言的灵活性,指针的应用,以及C语法的宽容性很容易造成代码的错误,这其中最主要的就是内存单元的溢出:1)堆栈溢出;2)缓冲区溢出;3)数组越界;因此将错误定位在一个函数内的时候,就应该关注内存的问题了;

 

 

 

18.        关注边界情况

程序中需要考虑的边界情况:1)数组的上限;2)循环的次数;3)链表的头部和尾部在插入新节点,或删除的情况下的特殊处理;4)输入参数的极限情况(0,指针为空,负数,最大的情况等等)。

 

 

 

 

 

阅读(1629) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~