动态内存分配——malloc()和free()

如果输入数据时,先告诉你个数,然后再输入,要记录每个数据。

C99可以用变量做数组定义的大小,C99之前呢?

int *a = (int*)malloc(n*sizeof(int));
代码如下:

#include<stdio.h>
#include<stdlib.h>

int main()
{
    int number = 0;
    int *a = 0;
    int i = 0;
    printf("输入数量:");
    scanf("%d",&number);
    a = (int*)malloc(number*sizeof(int));
    for( i = 0; i<number; i++)
    {
        scanf("%d",&a[i]);
    }
    for( i = number - 1; i>=0; i--)
    {
        printf("%d ",a[i]);
    }
    free(a);
}

 

malloc()

#include<stdlib.h>

void * malloc(size_t size);

1.向malloc申请的空间的大小是以字节为单位的

2.返回的结果是void*,需要类型转换为自己需要的类型

3.如果申请失败则返回0,或者NULL

 

试一试你的系统能给你多大的空间:

 

#include<stdio.h>
#include<stdlib.h>

int main()
{
    void *p;
    int cnt = 0;
    while(p = malloc(100*1024*1024))
    {
        cnt++;
    }
    printf("分配了%d00MB的空间\n",cnt);
    return 0;
}

 

在我的电脑(64位 WIndows10家庭中文版,4G内存)上只能分配1900M的空间。

下面是来自知乎的讲解:

地址空间限制是有的,但是malloc通常情况下申请到的空间达不到地址空间上限。内存碎片会影响到你“一次”申请到的最大内存空间。比如你有10M空间,申请两次2M,一次1M,一次5M没有问题。但如果你申请两次2M,一次4M,一次1M,释放4M,那么剩下的空间虽然够5M,但是由于已经不是连续的内存区域,malloc也会失败。系统也会限制你的程序使用malloc申请到的最大内存。Windows下32位程序如果单纯看地址空间能有4G左右的内存可用,不过实际上系统会把其中2G的地址留给内核使用,所以你的程序最大能用2G的内存。除去其他开销,你能用malloc申请到的内存只有1.9G左右。

其实,操作系统版本、程序本身大小、乃至的动态/共享库数量和大小、程序栈数量和大小等都会对其造成影响,甚至有些操作系统使用了一种叫做随机地址空间分布的技术(主要是出于安全考虑,防止程序受恶意攻击),使得进程的堆空间变小。

一个由C/C++编译程序占用内存分为以下几个部分
1、栈区(stack)— 由编译器自动分配释放 ,存放函数参数值,局部变量值等。其操作方式类似于数据结构中栈。
2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中堆是两回事,分配方式倒是类似于链表,呵呵。
3、全局区(静态区)(static)—,全局变量和静态变量存储是放在一块,初始化全局变量和静态变量在一块区域, 未初始化全局变量和未初始化静态变量在相邻另一块区域。 – 程序结束后由系统释放。–>分别是data区,bbs区
4、文字常量区 —常量字符串就是放在这里。 程序结束后由系统释放–>coment区
5、程序代码—存放函数体二进制代码。–>code区

而我们的malloc()申请的空间位于堆区,32位操作系统下理论最大可能申请到的空间是4G(内存达到4G且不算操作系统占用的内存时,实际做不到),64位操作系统下基本是根据内存决定的。

 

free()

1.把申请得来的空间还给“系统”

2.申请过的空间最终都应该还

3.只能还申请来的空间的首地址

4.free(0)和free(NULL)没问题,程序什么都不会归还

 

那么,malloc得到的空间是连续的吗?

逻辑地址连续,物理地址可以不连续。

malloc在大多实现中分配得到的内存空间比要求的大,额外空间记录管理信息——分配块的长度。

 

关于malloc(0)

1.来自C99的最权威的解释,malloc(0)是未定义行为:

2.返回一个地址空间是有意义的:为了和free的正常配对

3.malloc(0)的结果依赖实现

 

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注