- 简单说一下c语言中malloc函数的动态分配
malloc函数在linux终端下,敲 man malloc 就可以看到手册中malloc函数的详细介绍。可是。。。手册都是英文的啊!对于英文不好的我,读起来还是挺生硬。。。
void *malloc(size_t size);
void free(void *ptr);
void *calloc(size_t nmemb, size_t size);
void *realloc(void *ptr, size_t size);
void *reallocarray(void *ptr, size_t nmemb, size_t size);
以上这些函数呢,就是让程序猿来手动分配程序所需要的空间大小。函数用起来简单,重要的是理解,不然用了还是容易出错。所以下面主要写的是一些初步理解方面的,等到用得多了就能更有经验了。
与自动分配空间相比有下列一些区别:
时间不同
自动分配是编译器默认的类型(auto自动型),自动分配空间,自动回收空间。这一过程都是在编译时,编译器设定好的。而动态分配程序执行时,调用malloc等函数进行分配的。- 空间不同
我们把c语言编译后的应用程序在内存中的占用,按地址高低顺序分为以下部分:
- 栈区(stack)-存放函数的参数值,局部变量的值等。
- 堆区(heap)-由程序猿分配释放,若程序猿不释放,程序结束时可能由由系统自动回收 。
- 全局区(static)-存放的是全局变量和静态变量,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 程序结束后由系统释放。
- 文字常量区-常量字符串就是放在这里的。程序结束后由系统释放。
- 代码区-存放函数体的二进制代码。
malloc函数分配的区域就是堆区,程序猿利用malloc函数在堆区分配一个指定大小的空间。
动态分配的好处是:自由度大,想什么时候分配就什么时候分配,分配大小也自己定,不用受编译器和系统的太多限制。堆的空间还大。
但动态分配最致命的就是:内存泄露-指程序中动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。
自由的同时带来了麻烦!如果把自动分配比作孩子,内存空间比作生活的开销,系统和编译器就是父母。父母每月给孩子固定的money,省下来的money孩子自己偷偷买皮肤,没了父母给。而动态分配自己就是父母,只能自己替自己做主,每一笔开销都要打量着。花完之后,一个free函数,花完的钱又回来了(要是真的就好了),不free或者free错误直接破产。
下面来个错误示范
void test1(int *p,int n)
{
p = malloc(n);
if(p == NULL)
exit(1);
}
int main()
{
int num = 100;
int *p = NULL;
test1(p,num);
free(p);
return 0;
}
结果:
结果是空,什么也没有,也没有报任何错误。多么会钻空子的错误,main函数中free的p其实是main中的空指针,这两个函数中定义的都是局部变量,有作用域限制,这很简单的道理,但往往就会陷入这样的陷阱。free函数只释放之前调用 calloc、malloc 或 realloc 所分配的内存空间,对空指针不会进行任何操作,但也不会报错。
所以谨记:
* 成对使用,有一个malloc,就应该有一个free.
* 最好在同一调用层上使用这两个函数,不要像上面的错误示范一样。
* malloc分配的内存一定要初始化。free后的指针一定要设置为NULL。
以上就是初步的理解和使用。