1 GCC编译过程中的一些有意思的问题与过程
以下代码:
#include <stdlib.h>
#include <stdio.h>
#assert <assert.h>
int main ( int argc, char * argv)
{
void * memory = malloc(400);
assert (memory != NULL);
printf(" Yay!\b");
free(memory);
return 0;
}
如果注释掉#include <stdio.h>,printf 缺少声明,但是GCC一般不会报错程序还是能够link完成:
GCC会推测调用的函数的原型,在标准库中找到相应的原型;
注释掉#include <stdlib.h>,失去malloc 和 free 函数的原型,但是仍然能够通过最终链接;
注释掉#assert <assert.h>,编译时会生成的.o文件中会生成call assert()的汇编指令,导致最后链接失败(没有assert函数的实现定义)
注意:函数的原型能够在编译时在活动的栈记录中开辟出地址用于存储出函数形参的参数存储空间;
2 当函数调用参数多于原型的形参个数的情况:
int main ()
{
int num = 65;
int length = strlen( (char*)&num, num);
printf( "length = %d\n",length);
return 0;
}
(大端系统)程序最终会输出 0
编译时strlen函数()会开辟SP =SP-8的内存空间当函数原型参数的,而链接时根据标准库实际代码汇编结果,只会调用一个参数,得到相应的地址。会忽略参数个数的错误。(编译是编译,链接是链接)
3 参数写少了
int memcmp( void* v1); //原型搞错了、
{
int n = 17;
int m = memcmp(&n);
}
编译时函数只给了一个参数内存空间,链接时会按照库函数中的原型,将nm变量预先开辟的内存空间,作为函数参数进行运算;
4 debug 错误
seg fault : 尝试对空指针进行解引用
bus fualt:内存地址赋值错误(非法)(有点复杂)
5 数组越界问题
int main()
{
int i ;
int array[4];
for (i = 0; i<=4; i++{
array[i] = 0;}
return 0;
}
程序会死循环:array[4] =0 , 会导致栈区顶端 i =0;