月子会所网站源码,静态网页设计心得体会,甘肃张掖网站建设,手机网站制动态内存管理 1.1 为什么存在动态内存分配1.2 动态内存函数介绍2.1 malloc函数的使用2.2 free函数的使用2.3 calloc函数的使用2.4 realloc函数的使用3.1 常见的动态内存错误3.2 常见笔试题 1.1 为什么存在动态内存分配
我们已经掌握的内存开辟方式有#xff1a;
int val 20;… 动态内存管理 1.1 为什么存在动态内存分配1.2 动态内存函数介绍2.1 malloc函数的使用2.2 free函数的使用2.3 calloc函数的使用2.4 realloc函数的使用3.1 常见的动态内存错误3.2 常见笔试题 1.1 为什么存在动态内存分配
我们已经掌握的内存开辟方式有
int val 20;//在栈空间上开辟四个字节
char arr[10] { 0 };//在栈空间上开辟10个字节的连续空间
但是上述的开辟空间的方式有两个特点
1. 空间开辟大小是固定的。
2. 数组在声明的时候必须指定数组的长度它所需要的内存在编译时分配。
但是对于空间的需求不仅仅是上述的情况。有时候我们需要的空间大小在程序运行的时候才能知道
那数组的编译时开辟空间的方式就不能满足了。
这时就需要动态开辟内存了...1.2 动态内存函数介绍
开辟内存
void* malloc (size_t size);malloc函数是在堆中连续开辟size个字节的空间返回值为空间的起始地址开辟失败返回NULL指针 释放内存
void free (void* ptr);如果参数 ptr 指向的空间不是动态开辟的那free函数的行为是未定义的。 如果参数 ptr 是NULL指针则函数什么事都不做。 2.1 malloc函数的使用
#include stdio.h
#include errno.h
#include string.h
#include stdlib.h/*void* malloc( size_t size );
*/int main()
{int arr[10] { 0 };// 动态内存开辟int* p (int*)malloc(40); // 开辟40个字节if (p NULL){printf(%s\n, strerror(errno));return 1; // 给main函数返回1表示存在问题}// 使用int i 0;for (i 0; i 10; i){*(p i) i;}for (i 0; i 10; i){printf(%d , *(p i));}free(p); // 释放内存空间不然会内存泄漏,可以通过调试窗口 p,10 来观看数据p NULL; // 防止野指针因为它指向的空间已经释放了已经还给操作系统了p如果不置空的话这时候还记得地址return 0;
}还未free时的内存状态
free后的内存状况 pNULL 是为了防止野指针因为它指向的空间已经释放了已经还给操作系统了p如果不置空的话这时候还记得地址如果访问的话就非法访问内存了 2.2 free函数的使用
#include stdio.h
#include stdlib.h
int main()
{int a 10;int* p a; // 不是动态开辟的free(p);p NULL;int* p2 NULL; // 什么事都不做free(p2);return 0;
}free函数是只能释放动态内存的不是动态开辟的会报错 2.3 calloc函数的使用
void* calloc (size_t num, size_t size);函数的功能是为 num 个大小为 size 的元素开辟一块空间并且把空间的每个字节初始化为0。 与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全0。 #include stdio.h
#include stdlib.h
#include errno.h
#include string.h
int main()
{int* p (int*)calloc(10, sizeof(int));if (p NULL){printf(%s\n,strerror(errno));return 1;}int i 0;for (i 0; i 10; i) {printf(%d ,*(pi));}// 释放堆中的内存free(p);p NULL;return 0;
} 2.4 realloc函数的使用
void* realloc (void* ptr, size_t size);#include stdio.h
#include stdlib.h
#include errno.h
#include string.h
int main()
{int* p (int*)malloc(40);if (p NULL){printf(%s\n, strerror(errno));return 1;}int i 0;for (i 0; i 10; i){*(p i) i;}// 扩容// 要用新的指针来接收并且判断否则如果扩容失败会变成野指针本来指向40个字节扩容失败突然指向NULLint* ptr (int*)realloc(p, 80); if (ptr ! NULL){p ptr;}for (i 0; i 10; i){printf(%d , *(p i));}free(p);p NULL;return 0;
}需要注意的事realloc在开辟内存空间时存在2种情况 malloc和realloc函数的关联 #include stdio.h
#include stdlib.hint main()
{int* ptr (int*)realloc(NULL, 40); // 相当于 malloc(40)return 0;
}3.1 常见的动态内存错误
1.对NULL指针的解引用操作
#include stdio.h
#include stdlib.hint main()
{int* p (int*)malloc(40);if (p NULL) // err{return 1;}*p 20;free(p);p NULL;return 0;
}这里如果动态开辟内存失败p为NULL对NULL指针进行访问就会有问题 2. 对动态开辟空间的越界访问
#include stdio.h
#include stdlib.h
int main()
{int* p (int*)malloc(40);if (p NULL){printf(%s\n, strerror(errno));return 1;}int i 0;for (i 0; i 10; i) // 越界了{p[i] i;}free(p);p NULL;return 0;
}3. 对非动态开辟内存使用free函数
#include stdio.h
#include stdlib.hint main()
{int a 10;int* p a;free(p);p NULL;return 0;
}4. 使用free释放一块动态开辟内存的一部分
#include stdio.h
#include stdlib.hint main()
{int* p (int*)malloc(40);if (p NULL){return 1;}int i 0;for (i 0; i 10; i){// 这里p的位置被改变了free(p)时只释放掉了部分内存*p i;p;}free(p);p NULL; return 0;
}5. 对同一块空间的多次释放
#include stdio.h
#include stdlib.hint main()
{int* p (int*)malloc(40);free(p);p NULL; free(p);return 0;
}6.动态开辟内存忘记释放内存泄漏
#include stdio.h
#include stdlib.hvoid test()
{int* p (int*)malloc(100);int flag 0;scanf(%d,flag);if (flag 5){return;}free(p);p NULL;
}int main()
{test();return 0;
}当flag为5时就不会释放内存 3.2 常见笔试题
#include stdio.h
#include stdlib.h
#include string.hvoid GetMemory(char* p) // 堆中的p
{p (char*)malloc(100);
}
void Test(void)
{char* str NULL; // 栈中的pGetMemory(str); // 传递的是null不是str的地址strcpy(str, hello world); // 将str给到空指针printf(str);
}int main()
{Test();return 0;
}str为NULL传递给GetMemory函数GetMemory函数里的p是堆中的所开辟的p然后给它开辟空间然后返回到Test函数这时的str依旧为NULL然后调用strcpy函数是把hello world给到NULL指针会出现错误。 #include stdio.hchar* GetMemory(void)
{char p[] hello world; // 这里是局部变量放置在栈中, 函数执行完就被销毁了还给操作系统了//char* p hello world; return p;
}
void Test(void)
{char* str NULL;str GetMemory(); // 野指针非法访问内存了printf(str);
}int main()
{Test();return 0;
} 这里GetMemory后返回的是局部变量的地址放在栈中但是这个函数执行完后这个变量就被销毁了所以再通过指针访问这块内存空间就是非法访问内存了。 #include string.h
#include stdio.h
#include stdlib.hvoid GetMemory(char** p, int num)
{*p (char*)malloc(num);
}
void Test(void)
{char* str NULL;GetMemory(str, 100);strcpy(str, hello);printf(str);// 下列为修改后的代码//free(str);//str NULL;
}int main()
{Test();return 0;
}这个很容易动态开辟内存后未能后free