1. 内存分配方式
1) 从静态存储区分配, 如全局变量 / static变量。
2) 从栈上创建,如函数内局部变量,自动被释放。
3) 从堆上分配,即是动态分配,用malloc / free 申请和释放(配对使用)。
2. 常见内存错误
1) 内存分配没有成功却使用了它, 使用前检查是否为NULL
2) 内存分配成功,但是没有初始化就引用它。
3) 内存分配成功并初始化, 但操作越过内存边界
4) 忘记释放内存,造成内存泄漏。
5) 释放了内存却继续使用它, 释放后记得设置为NULL
3. 指针与数字对比
1.1) 指针可指向任意类型的内存块,
1.2) 数组要么在静态存储区被创建,要么是在栈上被创建, 数组名对应(不是指向)一块内存。
char *p = "world";
p[0] = 'X';
编译器不能发现上面错误,注意p是指向常量字符串
2) 不能对数组名直接复制,要用标准库函数 strcpy() 进行复制,比较用 strcmp();
3) C++ / C 无法知道指针所指向的内存容量;
char a[] = "hello world";
char *p = a;
printf("a = %d", sizeof(a)); //12字节
printf("p = %d", sizeof(p)); //4字节
4) 数组退化为指针
void fun(char a[100])
{
printf("a = %d", sizeof(a)); //4字节不是100字节
}
4. 指针参数如何传递内存
1) 用指向指针的指针申请动态内存
void getmemory(char **p, int num)
{
*p = (char *)malloc(sizeof(char) * num);
}
void test(void)
{
char *str = NULL;
getmemory(&str, 100); //注意是 &str, 不是str
strcpy(str, "good");
printf("%s", str);
free(str); //记得释放内存
}
2) 用函数返回值来传递内存
char *getmemory(int num)
{
char *p = (char *)malloc(sizeof(char) * num);
return p; //注意不要返回指向“栈内存”的指针
}
void test(void)
{
char *str = NULL;
str = getmemory(100);
strcpy(str, "good");
printf("%s", str);
free(str); //记得释放内存
}
5. 杜绝野指针
“野指针”不是NULL指针,是指向垃圾内存的指针。
1) 指针变量没有初始化。
2) 指针变量被 free 或者 delete 之后,没有置为NULL,让人误以为是一个合法的指针。
3) 指针操作超越了变量的作用范围。
6. malloc / free 使用要点
1) malloc 返回值类型为 void *,所以调用malloc是要显式进行类型转换。
2) malloc 里面的参数 要使用 sizeof 运算符来确定数据类型的确切字节数。
摘自《高质量程序设计指南——C++/C语言》第11章,P130-P145