第三章 机器的程序级表示(下)
数据传送:
当过程P调用过程Q时,P的代码必须首先把参数复制到适当的寄存器中。类似的,当Q返回到P时,P的代码可以访问寄存器中的返回值;
每个过程调用在栈中都有它自己的私有空间,因此,多个未完成调用的局部变量不会相互影响。当过程被调用时分配局部存储,当返回时释放存储;
数组的分配和访问:
对于数据类型T和整型常数N,数组表现形式如下:T A[N]。它表示在内存中分配一个L*N字节的连接区域,这里L是数据类型T的字节大小。当然,A也可以用来作为指向数组开头的指针。如:
char A[12];
char *B[8];
声明一个数组 T D[R][C],它的数组元素D[i][j]的内存地址为: D地址 + L( i * C + j )
比如,int A[5][3],其中,C的值即列数3,L即int类型的字节长度4,所以,数据元素A[i][j] 的内存地址为:A数据地址 + 4*(3*i+j)
定长数组:当程序要用一个常数作为一个数组的维度或者缓冲区的大小时,最好通过#define声明这个常数与一个名字联系起来,然后在后面一直使用这个名字来替代常数的值。这样,如果需要修改这个值,直接改这个#define声明就好了。如
#define N 16;
typedef int fix_matrix[N][N];
变长数组:数组在被分配时才计算出来数组长度大小,一般都是使用malloc这种函数来为这些数组分配存储空间;如,int A[expr1][expr2],如果A数组作为一个函数参数,那么,在调用函数,遇到这个声明的时候,通过对表达式exp1和exp2求值来确定数组的维度;
异质的数据结构:
使用struct来声明,将可能多个不同类型的对象聚合到一个对象中。如:
缓冲区溢出:C对于数组引用不进行任何边界检查,而且局部变量和状态信息都是存放在栈中。这两种情况结合到一起就能导致严重的程序错误,对越界的数组元素的写操作会破坏存储在栈中的状态信息。通常,当栈中分配某个字符数组来保存一个字符串,但是字符串长度超出了为数组分配的空间。
对抗缓冲区溢出攻击机制:
1.栈随机化
2.栈破坏检测;
3.限制可执行代码区域;
上面的方法都是由编译器或操作系统完成的,无需程序员主动关心。
作者:凌晨六点半
出处:http://www.cnblogs.com/sunnyDream/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利。
如果您认为这篇文章还不错或者有所收获,您可以通过右边的“打赏”功能 打赏我一杯咖啡【物质支持】,也可以点击右下角的【好文要顶】按钮【精神支持】,因为这两种支持都是我继续写作,分享的最大动力!