1.一般来说,我们可以简单地理解为内存分为3个部分:堆,栈和静态区。堆栈就是栈,而不是堆。堆的英文是heap;栈的英文是stack,也翻译为堆栈。
1)堆:由malloc系列函数或new操作符分配的内存。其生命周期又free或delete决定,在没有释放之前一直存在,直到程序结束。其特点是使用灵活,空间比较大,但容易出错。
2)栈:保存局部变量。栈上的内容只在函数的范围内存在,当函数运行结束,这些内容也会自行销毁。其特点是效率高,但空间大小有限。
3)静态区:自动保存全局变量和static变量(包括static全局和局部变量)。静态区的内容在整个生命周期内存在,由编译器在编译的时候分配。
4)指针没有指向一块合法的内存,定义了指针变量,但是没有为指针分配内存,即指针没有指向一块合法的内存
1°结构体成员未初始化
struct
{
char *name;
int score
}stu,*pstu;
int main()
{
strcpy(stu.name,"Tom");
stu.score = 99;
return 0;
}
很多初学者犯了这个错误不知道是怎么回事,这里定义了结构体变量stu,但是他没想到这个结构体内部char* name,该成员在定义结构体变量stu时,只是给name这个指针变量分配了四个字节,name指针本身没有指向一个合法的地址,这时候其内部存的都是一些乱码,所以在调用strcpy函数时,会将字符串“Tom”往乱码里所指的内存上复制,而这块内存name指针根本就无权访问,导致出错,解决的方法是为name指针malloc一块空间
2°没有为结构体指针分配足够的内存
3°函数的入口检验
不管什么时候,我们使用指针之前一定要确保指针是有效的。
一般在函数入口处使用assert(NULL != p)对参数进行检查,在非参数的地方使用if(NULL != p)来校验。但这里都有一个要求,即p在定义的时候同时初始化为NULL。
assert是一个宏。而不是函数,包含在assert.h 头文件中,这个宏只在Debug版本上起作用,而在Release版本中被编译器完全优化掉,这样就不会影响代码的性能。
struct
{
char *name;
int score
}stu,*pstu;
int main()
{
strcpy(stu.name,"Tom");
stu.score = 99;
return 0;
}