内存管理
内存分区
- 常量区
- 栈区
- 全局区
- 静态区
- 堆区
常量区
- 整形常量
- 浮点常量
- 字符常量
- 字符串常量
- 地址常量:数组名、函数名
特点:
不可修改
栈区
- 局部变量
- 函数形参
特点:
租来的房子,房子到期自动回收
- 访问速度快
- 空间少
- 生命周期和作用域从定义的位置开始到“}”结束
全局区
全局变量
特点:
- 局部大于全局
- 默认初始化0
- 生命周期 程序开始到程序结束
- 作用域 整个项目
在其他文件中使用全局变量
/*a.c*/
extern int g_value;//全局变量的声明
void setValue(int g) {
g_value = g;
}
/*main.c*/
#include <stdio.h>
int g_value = 100;
int main(int argc, char __ argv){
setValue(200);
printf("%d\n", g_value);
return 0;
}
静态区
静态局部变量
特点:
- 生命周期 程序开始到程序结束
- 作用域 从定义的开始到“}”结束
- 只被初始化一次
静态全局变量
#include <stdio.h>
void getValue(){
static int s = 10;
int n = 10;
printf("%d ", s++);
printf("%d ", n++);
}
int main(){
getValue();//10 10
getValue();//11 10
return 0;
}
特点:
- 生命周期 程序开始到程序结束
- 作用域 当前文件
堆区
特点:
自己买的房子,不会自动释放
- 不会自动释放
- 容量大
- 访问速度慢
- 堆区空间没有名字
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
char *p = malloc(500); // 在堆区分配500个字节的空间 => char p[500];
p[0] = 'a';
p[1] = 'c';
strcpy(p, "abcdef");
printf("%s", p);
free(p);//不用时,一定手动释放空间
return 0;
}
char *p = malloc(500); <==> char p[500];
GetMemory的几个笔试题
Getmemory的几个经典的关于内存的笔试题
输出结果以及出现的错误
Test1
void GetMemory1(char* p) {
p = (char *)malloc(100);
}
void Test1() {
char* str = NULL;
GetMemory1(str);
strcpy(str, "hello world");
printf(str);
}
p
是值传递,str
不会被改变
修改方法:
- 将
GetMemory1()
返回值类型改为char *,返回堆区的地址,并用str
接收
char* GetMemory1(void) {
return (char *)malloc(100);
}
void Test1() {
char* str = NULL;
str = GetMemory1();
strcpy(str, "hello world");
printf(str);
free(str);
str = NULL;
}
- 将
GetMemory1()
的参数类型改为二级指针,传入str
的地址即可
void GetMemory1(char** p) {
*p = (char *)malloc(100);
}
void Test1() {
char* str = NULL;
GetMemory1(&str);
strcpy(str, "hello world");
printf(str);
free(str);
str = NULL;
}
Test2
char* GetMemory2() {
char p[] = "hello world"; //p是局部变量
return p; //试图返回局部变量的地址
}
void Test2() {
char* str = NULL;
str = GetMemory2();
printf(str);
}
p
中存放的是栈区的地址,函数结束后栈区数据被释放
修改方法:Test3 or Test4
Test3
char* GetMemory3() {
char *p = "hello world"; //p是局部变量
return p; //返回常量的地址
}
void Test3() {
char* str = NULL;
str = GetMemory3();
printf(str);
}
输出:“hello world”
Test4
char* GetMemory4() {
static char p[] = "hello world";
return p;
}
void Test4() {
char* str = NULL;
str = GetMemory4();
printf(str);
}
输出:“hello world”
Test5
void Test5() {
char* str = (char*)malloc(100);
strcpy(str, "hello");
free(str); // 堆存放的数据释放
//str = NULL //为了防止访问非法的空间,释放后,指向NULL
if (str != NULL) {
strcpy(str, "wold");
printf(str);
}
}
堆空间已经释放,访问非法
修改方法:
- 将
free()
移动到程序末尾
Test6
void Test6() {
char* str = (char*)malloc(100);
strcpy(str, "hello");
str += 6;
free(str); // str已经被修改 无法正常释放
//str = NULL
if (str != NULL) {
strcpy(str, "wold");
printf(str);
}
}
释放时地址应和申请时的地址一致
修改方法:
- 删除
str += 6;
,并将free()
移动到程序末尾